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 <stdio.h> */ import "C" type File C.FILE const Sizeof_File = C.sizeof_FILE
cgo -godefs 是专门用来将c语言结构体转换成golang语言对应的结构体的工具。
4、示例:
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
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 }
有疑问加站长微信联系(非本文作者)
本文来自:博客园
感谢作者:welhzh
查看原文:将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct