博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct...
阅读量:7078 次
发布时间:2019-06-28

本文共 4684 字,大约阅读时间需要 15 分钟。

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的函数,但我未验证过):

working with a lot of typedefs in cgo is a real pain (Go's typing rules are simply too strict
for a C programmer).
I'd suggest you create a wrapper function in C (or Go) to create the structure for you. 
 
for printing, you can define the String method on real type of structure (it won't be portable,
as it depends the real type name of the C struct, but it's certainly doable, and will save you
a lot of work if you're debugging a C-Type-rich application)
For example,
 
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))))) }
3、上面第二步的做法并不安全,因为这种程序员自己定义的golang语言结构体可能和c语言的结构体并不一一对应,因此应该用下面的方法:
This is not safe and Go doesn't guarantee compatible struct layout rules with gcc.
 
for example, 8g currently aligns uint64 only to 4-byte boundary, but gcc aligns it to 8-byte boundary.
If you want compatible structure layout, you can use "cgo -godefs".
 
for example, given file.go:
package main /*#include 
*/import "C" type File C.FILEconst Sizeof_File = C.sizeof_FILE
 
go tool cgo -godefs file.go                will generate a Go definition of type File that matches that of C's FILE.

cgo -godefs  是专门用来将c语言结构体转换成golang语言对应的结构体的工具。

 

4、示例:

package main/*#include 
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 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}

 

转载地址:http://llpml.baihongyu.com/

你可能感兴趣的文章
neo4j开发
查看>>
系统规划笔记
查看>>
jtds用PreparedStatement查询大数据时慢的问题(轉)
查看>>
jsp中include指令静态导入和动态导入的区别详解
查看>>
Java构造和解析Json数据的两种方法详解一
查看>>
CopyOnWriteArrayList
查看>>
TI-89T 的二次开发思路
查看>>
CentOS上mysql5.7.23安装
查看>>
二分查找
查看>>
如何配置JVM参数
查看>>
几个支持中文的PHP字符串截取函数
查看>>
关系型数据库遵循ACID规则
查看>>
DUBBO Thread pool is EXHAUSTED! 的问题
查看>>
zepto之tap点透处理
查看>>
Android中BindService方式使用的理解
查看>>
2.每获取一个socket,就创建一个线程用于处理这个socket。
查看>>
Android 锯齿数组用于RBAC权限管理
查看>>
23.centos中文字体安装--2013-06-04
查看>>
视频和音频开源项目
查看>>
【工具使用系列】关于MATLAB数据和函数的可视化,你需要知道的事
查看>>