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. JS 如何将“在线图片资源”转换成“base64”

    在实现html2canvas截图的功能时,会报下面的错误: Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasEle ...

  2. 九、K3 WISE 开发插件《工业单据老单序时薄插件工具栏按钮开发实例》

    =============================== 目录: 1.添加工具栏按钮 2.查询被添加工具栏按钮的业务单据的FMenuID和FID 3.添加工具栏按钮和业务单据的映射关系 4.工具 ...

  3. nuxt项目中vue报错The client-side rendered virtual ...

    报错: 翻译过来是: [Vue警告]:客户端呈现的虚拟DOM树与服务器呈现的内容不匹配.这可能是由不正确的HTML标记引起的,例如在其中嵌套块级元素或丢失.Bailing水化和执行完整的客户端渲染. ...

  4. kafka+zookeeper环境配置(linux环境单机版)

    版本: CentOS-6.5-x86_64 zookeeper-3.4.6 kafka_2.10-0.10.1.0 一.zookeeper下载与安装 1)下载 $ wget http://mirror ...

  5. 我是怎样使用javassist将代码注入到帝国OL并进行调试的

    帝国OL是拉阔一款手机网络游戏(腾讯也有代理),我在中学时代玩儿过. 帝国OL还维护着KJava版本游戏客户端,这意味着我们可以在PC端使用模拟器玩儿游戏. 不过这篇文章我主要是关注如何通过代码注入拦 ...

  6. h5 . css入门 2.CSS基础

    CSS基础 学习目标 1.CSS简介 2.CSS语法 3.样式的创建 4.两种引入外部样式表的区别 5.样式表的优先级和作用域 6.CSS选择器 7.选择器的权重 8.浮动属性的简单应用 9.HTML ...

  7. Windows Server 2008 R2远程协助选项 灰色

    管理工具——〉服务器管理器——〉功能——〉添加功能   窗口中"远程服务器管理工具"下边的"远程协助"打上对钩"再点击"下一步"再 ...

  8. TOP100summit2017:网易云通信与视频CTO赵加雨:外力推动下系统架构的4个变化趋势

      壹佰案例:很荣幸邀请到您成为第六届壹佰案例峰会架构专场的联席主席,您曾深度参与Cisco Jabber,Webex Meeting, Cisco Spark等多项分布式实时通信类产品的架构与研发, ...

  9. jdbc-------JDBCUtil类 工具类

    jdbcutil 主要处理的是 连接数据库, 和关闭各个流 1, 数据库连接的配置信息: mysql.properties (在工程的目录下)个人配置 url=jdbc:mysql://localho ...

  10. CH 3401 - 石头游戏 - [矩阵快速幂加速递推]

    题目链接:传送门 描述石头游戏在一个 $n$ 行 $m$ 列 ($1 \le n,m \le 8$) 的网格上进行,每个格子对应一种操作序列,操作序列至多有 $10$ 种,分别用 $0 \sim 9$ ...