cgo的效率 golang_golang CGO FAQ & TIPS : cgo 从 C 传递 slice 到 go

本文介绍了如何在C语言的回调中通过cgo将C的slice传递给Go,以及如何使用Go的SetFinalizer方法自动化回收C.CString创建的内存。同时讨论了C语言中bool类型的转换问题,提供了相应的转换策略。
摘要由CSDN通过智能技术生成

cgo 从 C 传递 slice 到 go

这里一般会用在c的callback中。

需要加一个wrapper,比直接调用go函数中间多了一个转换步骤,但方便了许多。

执行流程为,c调用发起 -> c wrapper -> go export

.go:

//export a_function_callback

func a_function_callback(args []C.astruct) {}

.c:

extern void a_function_callback(GoSlice args);

void a_function_callback_c(args *C.astruct) {

GoSlice args_go;

args_go.data = args;

args_go.len = nargs;

args_go.cap = nargs;

return a_function_callback(args_go);

}

这里的GoSlice需要从 export 出来的 .h 中获取,或者 include 该 .h文件。

也可以直接拷贝过来,注意不要产生类型冲突。

#ifndef GO_CGO_PROLOGUE_H

#define GO_CGO_PROLOGUE_H

typedef long long GoInt64;

typedef GoInt64 GoInt;

typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

C.CString 的自动化回收方法

一般使用 C.CString 时,定义一个临时变量存储结果,使用 defer C.free 回收这个临时的变量。

在 go 的 runtime 包中,有一个SetFinalizer方法,可以在回收对象的时候调用一个处理函数。

那么我们可以考虑使用它来自动化回收 C.CString产生的临时变量。

type CString struct {

Ptr *C.char

}

func CCString(s string) *CString {

p := C.CString(s)

this := &CString{Ptr: p}

runtime.SetFinalizer(this, freeCString)

return this

}

func freeCString(cs *CString) {

C.free(unsafe.Pointer(cs.Ptr))

}

在使用的时候,基本能嵌入到调用的位置,不需要显式定义一个临时变量并执行 defer C.free。

C.somefunc(CCString(s).Ptr)

注意,只在somefunc不接管传递的参数的所有权时调用这种方式,如果somefunc接管了所有权,

而在未来某时间内存被回收了,则会出现程序SEGFAULT崩溃。

这种可能会产生一点runtime效率损失,另外还有额外的内存分配,看情况使用。

bool 类型的转换处理

在 C 语言中,c99之前 bool 都是定义为 int的,要想转换为go的bool类型,比较曲折。

var bval_c C.GBoolean

var bval_go bool

if int(bval) == 1 {

bval_go = true

} else {

bval_go = false

}

如果go有三元运算符的话,也可一行代码实现该转换,问题是go没有三元运算符。

一般来说,对其包装一个简单的转换函数比较好,比如 c2gobool(C.GBoolean).

有时候不同的 C 项目中 bool 定义不同,所以一般需要为每个项目定义这么一个函数,而不能放在一个库中共用。

在 c99 之后,则没有这个问题,cgo能够直接判断是内置的bool类型,能够直接转换为go的bool。

var bval_c C._Bool

var bval_go = bool(bval_c)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值