Pass struct and array of structs to C function from Go

I know this is a fairly old topic but I stumbled across it. Here's a modified (correct) version with some additional manipulation from C land on the Go structs.

package main

/*
#include <stdio.h>

typedef struct {
    int a;
    int b;
} Foo;

void pass_struct(Foo *in) { printf("%d : %d\n", in->a, in->b); }

void pass_array(Foo **in, int len) {
    for(int i = 0; i < len; i++) {
        pass_struct(in[i]);
        in[i]->a += 1;
        in[i]->b += 1;
    }
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

type Foo struct{ a, b int32 }

func main() {
    foo := Foo{10, 20}
    foos := []*Foo{&Foo{1, 2}, &Foo{3, 4}}

    fmt.Println("from C land")
    C.pass_struct((*C.Foo)(unsafe.Pointer(&foo)))
    C.pass_array((**C.Foo)(unsafe.Pointer(&foos[0])), C.int(len(foos)))
    fmt.Println("a & b should have incremented with 1")

    fmt.Println("from Go land")
    for _, foo := range foos {
        fmt.Printf("%d : %d\n", foo.a, foo.b)
    }
}

Output:

from C land
10 : 20
1 : 2
3 : 4
a & b should have incremented with 1
from Go land
2 : 3
4 : 5

The problem is that Foo and _Ctype_Foo are different structures.

I would guess you are running on 64 bit. Note that int is 64 bit in go, but is quite likely to be 32 bit in C.

If I change the definition of Foo to this then it works on my machine (64 bit linux)

type Foo struct {
    A int32
    B int32
}

However I would say that is a recipe for trouble - make your Go and C code use the same structure with

type Foo _Ctype_Foo

Tags:

Go

Cgo