https://groups.google.com/forum/#!topic/golang-nuts/JkvR4dQy9t4
https://golang.org/misc/cgo/gmp/gmp.go
https://stackoverflow.com/questions/19910647/pass-struct-and-array-of-structs-to-c-function-from-go
https://studygolang.com/articles/6367
1、可以为c struct定义结构体函数,如下定义的打印函数,(你可能还可以定义改变结构体内部子field的函数,但我未验证过):
package main /*struct CType { int a; char b; float c;};*/import "C" import "fmt" func (c _Ctype_struct_CType) String() string { return "hello" } func main() { fmt.Printf("%v\n", C.struct_CType{})}
其中的 _Ctype_struct_CType 寒气来有点奇怪,起始不用惊慌,可以用后面的方法自动得到这种奇怪的命名的。
当然,上面的只是演示为 c struct 定义内置函数。如果你仅仅是在golang中打印 c struct,只需要像普通变量一样直接传给Print就可以了,如: fmt.Printf("%v\n", C.objstruct) 或 fmt.Println(C.objstruct)。
2、你可以将整个golang的结构体指针转换成c语言的结构体指针,前提是golang 的结构体和c 的结构体定义是一一对应的(后面有介绍怎么穿件一一对应的结构体),但是c语言的结构体指针无法直接转换成golang语言的结构体指针:
You can cast the entire struct via intermediate pointers. The conversion should work in either direction. There are probably other ways too, like encoding/binary. An example of the pointer approach follows:
package main import ( "fmt" "unsafe") // struct x {// int y, z;// };//// int sum(struct x a) {// return a.y + a.z;// }//import "C" type X struct{ Y, Z int32 } func main() { a := &X{ 5, 7} fmt.Println(a, "->", C.sum(*((*C.struct_x)(unsafe.Pointer(a))))) }
package main /*#include*/import "C" type File C.FILEconst Sizeof_File = C.sizeof_FILE
cgo -godefs 是专门用来将c语言结构体转换成golang语言对应的结构体的工具。
4、示例:
package main/*#includetypedef 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 land10 : 201 : 23 : 4a & b should have incremented with 1from Go land2 : 34 : 5
5、示例2:
将c语言的 char * 指针copy成 golang 的byte slice:
// convert c language char* to golang byte slice, and COPY source datas into dest slice packet *C.char // 该变量在c语言里赋值 vlen := 512 b := make([]byte, vlen) ii := C.int(0) for i := 0; i < vlen; i++ { ii = C.int(i) // this is copy, not equal to the orignal pointer b[i] = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(packet)) + uintptr(unsafe.Pointer(C.int_to_charp(ii))))) }
我自己的转换的示例:
c语言定义的结构体:
struct dnet_host { struct dnet_key key; char name[DNET_HOST_NAME_MAX]; char version[16]; time_t last_active; time_t last_appear; time_t last_time_changed; uint32_t crc32; uint32_t route_ip; unsigned name_len; uint16_t route_port; uint8_t is_local; uint8_t is_trusted; enum dnet_host_route_types route_type;};
转成golang对应的结构体 (type DH C.struct_dnet_host):
type DH struct { Key _Ctype_struct_dnet_key Name [256]int8 Version [16]int8 Last_active int64 Last_appear int64 Last_time_changed int64 Crc32 uint32 Route_ip uint32 Name_len uint32 Route_port uint16 Is_local uint8 Is_trusted uint8 Route_type uint32 Pad_cgo_0 [4]byte}