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{, }
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 <stdio.h>
*/
import "C" type File C.FILE
const 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 <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{, }
foos := []*Foo{&Foo{, }, &Foo{, }} fmt.Println("from C land")
C.pass_struct((*C.Foo)(unsafe.Pointer(&foo)))
C.pass_array((**C.Foo)(unsafe.Pointer(&foos[])), 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
:
:
:
a & b should have incremented with
from Go land
:
:

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 :=
b := make([]byte, vlen)
ii := C.int()
for i := ; 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[];
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 []int8
Version []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 []byte
}

将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct的更多相关文章

  1. C语言基础知识点整理(函数/变量/常量/指针/数组/结构体)

    函数 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ...

  2. C语言 指向结构体变量的指针

    一个指向变量的指针表示的是占内存中起始位置 一个指向结构体的变量的指针表示的是这个结构体变量占内存中的起始位置,同样它也可以指向结构体变量数组 定义结构体变量的指针: //假设已有一个结构体名为Stu ...

  3. 你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06

    再续前文,在面向对象层面,Python做到了超神:万物皆为对象,而Ruby,则干脆就是神:飞花摘叶皆可对象.二者都提供对象类操作以及继承的方式为面向对象张目,但Go lang显然有一些特立独行,因为它 ...

  4. 结构体struct sockaddr_in, struct sockaddr,struct in_addr

    一.结构体 struct sockaddr_in,  struct sockaddr,  struct in_addr struct sockaddr_in,  struct sockaddr,str ...

  5. 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

    转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq  结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看 ...

  6. (转)类(class)和结构(struct)的区别是什么?它们对性能有影响吗?.NET BCL里有哪些是类(结构),为什么它们不是结构(类)?在自定义类型时,您如何选择是类还是结构?

    转自:http://blog.csdn.net/lingxyd_0/article/details/8695747 类(class)和结构(struct)的区别是什么?它们对性能有影响吗?.NET B ...

  7. C/C++中指向结构体变量的指针,调用指向的那个结构体中的成员

    设p是指向结构体变量的指针,则可以通过以下的方式,调用指向的那个结构体中的成员: (1)结构体变量.成员名.如,stu.num. (2)(*p).成员名.如,(*p).num. (3)p->成员 ...

  8. [转载]彻底弄清struct和typedef struct

    struct和typedef struct 分三块来讲述: 1 首先://注意在C和C++里不同 在C中定义一个结构体类型要用typedef: typedef struct Student { int ...

  9. struct和typedef struct彻底明白了

    struct和typedef struct 分三块来讲述: 1 首先://注意在C和C++里不同 在C中定义一个结构体类型要用typedef: typedef struct Student { int ...

随机推荐

  1. mysql性能调整三板斧

    大意是,用2/8原则,多快好省的解决大部分事情.所以三板斧,仅限整体调整,不牵扯具体细节. 1.innodb 使用innodb引擎 2.innodb_buffer_pool 调整和innodb有关的参 ...

  2. SafetyNet Attestation API

    https://developer.android.google.cn/training/safetynet/attestation#verify-compat-check  SafetyNet At ...

  3. 9.24 Django Form组件

    2018-9-23 20:10:04 这两天优化了自己图书管理系统 github 连接:https://github.com/TrueNewBee/pythonDemo 顺便整理了博客,写了好多总结, ...

  4. Flask web开发之路八

    今天写Flask_SQLAlchemy的外键及其关系 ### Flask-SQLAlchemy外键及其关系: 主app文件代码: from flask import Flask from flask_ ...

  5. 解决Hibernate:could not initialize proxy - no Session(申明:来源于网络)

    解决Hibernate:could not initialize proxy - no Session 地址:http://blog.csdn.net/chenssy/article/details/ ...

  6. zabbix监控告警Received empty response from Zabbix Agent Assuming that agent dropped connection

    zabbix监控告警Received empty response from Zabbix Agent Assuming that agent dropped connection错误 查看zabbi ...

  7. Error:..\FreeRTOS\portable\RVDS\ARM_CM3\port.c,378 Error:..\FreeRTOS\portable\RVDS\ARM_CM3\port.c,378 Error:..\FreeRTOS\portable\RVDS\ARM_CM3\port.c,378 Error:..\FreeRTOS\tasks.c,2806

    Error:..\FreeRTOS\portable\RVDS\ARM_CM3\port.c,378Error:..\FreeRTOS\portable\RVDS\ARM_CM3\port.c,378 ...

  8. hbase与hive集成:hive读取hbase中数据

    1.创建hbase jar包到hive lib目录软连接 hive需要jar包: hive-hbase-handler-0.13.1-cdh5.3.6.jar zookeeper-3.4.5-cdh5 ...

  9. CentOS7初始化mysql库报错

    在centos7上安装mysql数据库,进行数据库初始化工作时,报错缺少data::dumper库文件,如下: 解决办法:安装autoconf库后重新初始化即可解决. yum-y install au ...

  10. dos基本指令

    目录操作 dir  操作磁盘文件目录 md / mkdir <folder name> 创建子目录make directory cd  改变当前工作目录,返回上一级 cd .. rd  删 ...