cgo与调用c的回调函数指针

cgo直接调用函数,使用基本数据类型非常简单,包括一些结构体也比较简单,嵌套的稍微复杂些,但也可以,但有的时候,cgo调用c函数,会需要传递一个回调函数的指针,这时候就比较复杂了,要比python的ctypes复杂很多,python可以用winfunc很轻松去创建这样的函数,但是对于 go 这种编译型语言来说,就很麻烦了,实际上是如下操作:

先看官方代码:

这块是头文件的声明

一、构造包装函数(callOnMeGo_cgo),这里通过cgo编写一个自己的c函数,满足要调用库的callback格式就可以。

原理就是利用cgo在go代码里创建一个符合调用约定的真正的c函数(壳子),用它二次调用Go的实际回调函数,因为C语言不能直接接受Go的函数指针调用。这个壳子里面什么都没有,只是转发。当然内部也是可以写一些代码的,例如,数据的二次检查、包装等。

这里int callOnMeGo(int);的函数声明,可以放到函数体外面去,便于查看。

如果只需要结构体某些字段,可以直接在这里提取后转发过去,省略了Go语言中操作的步骤。 

二、用包装函数调用真正的go函数(callOnMeGo),然后就可以实现回调了

这里主入口,记得声明下步骤一这个自己定义的包装函数的结构;

问题解决:

1.传参后,回调函数调用没效果:

一般这种都是回调函数的参数类型不对,比如说void *传unsafe.pointer是可以的;但是结构体指针不能传unsafe.pointer,可直接声明C.STRUCTXXX,是指针就传* C.STRUCTXXXX

注意,回调参数有问题, 请看下引用的C或者C++ SDK 自己的日志,go程序是不会有任何反应的。

2.编译报错

编译报错需要检查

①.是否注释内部有嵌套,有的需要删掉或者拿出去

②.头文件的struct是否带 tag 不带tag 需要增加

③. 是否出现了释放不该释放的内容,比如说,回调传过来的结构体,通过var声明后,就进入到了Go的GC范围内,不要去C.free

④.是否有C++的东西,如果有C++的东西需要转换成C语言

⑤.编译的平台需要一致,编译时,需要编译整个package;64位的lib,需要 64 位的cgo编译 

⑥.编译后导入表会对指定函数有强依赖,必须带入依赖库,运行时不像syscall可以懒加载。

⑦.CFLAGS、LDFLAGS的参数是否完整,比如说没有使用-l指定对应的lib

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值