cgo 数据_cgo的一些经验

本文详细介绍了在Go语言中使用cgo进行C语言交互时需要注意的要点,包括类型转换、字符串处理、结构体、指针操作以及函数调用。通过示例代码展示了如何安全地进行C函数调用、内存管理和数据转换。同时强调了Go语言与C语言在类型系统上的差异,以及Go语言中对指针操作的限制。
摘要由CSDN通过智能技术生成

cgo可以在go语言中夹杂着C函数或数据,在使用cgo时,有一些需要注意的:

1、go中的int/int32/int64/uint32/uint64和C语言中的int/int32等是不同的,因此,C语言的函数的参数不能是go语言的int,需要转换,同理,go函数的int也不能使用C的int,需要转换。

go int转换为C int的方法:

C.int(n)

还有一点,C的函数调用中,有很多参数是size_t类型,其实就是一个整型,但如果使用C.int()作为C函数的参数,就会编译出错:

cannot use _Ctype_int(100) (type C.int) as type C.size_t in function argument

go编译器严格限制参数类型必须一致,因此必须是size_t类型的参数。这是因为go语言没有C语言里面的强制转换的概念,你可以使用

C.size_t(n)来得到C语言中的sizt_t类型。

2、go语言中的字符串和C语言中的字符串转换

C.Cstring

C.GoString

….

具体可以参考文档。

3、结构体

使用C.struct_xxxx

如果使用struct中的成员变量,可以直接用.来访问。

4、指针

使用unsafe.Pointer()来转换,例如需要转换为 int *:

(*C.int)(unsafe.Pointer(&v))

在c语言中,指针即数组,可以使用ptr[n]来获得指针的第n个偏移,但在go中,这样不行,会报错:

invalid operation:xxxx

go语言中,指针没有这样的操作。

需要使用unsafe.Pointer和uintptr配合来获取指针的偏移。

5、函数调用

C.func()

文档中说,go调用所有的C函数都会返回两个值,后一个值为error类型,即使是void函数。文档表述如下:

n, err := C.sqrt(-1)

_, err := C.voidFunc()

但我发现,C.malloc似乎只返回一个值。

6、C语言中的NULL在go中是nil

例如

s := C.malloc(C.sizeof(100))

if s == nil {

….

}

这个很重要,在没发现nil可以比较c的指针前,我是这样比较的:

(*C.char)(unsafe.Pointer(uintptr(0)))

不过,cgo的文档还很匮乏,很多都需要阅读代码。

package main

/*

#include #include #include

struct t {

char *s;

};

*/

import “C”

import “unsafe”

import “fmt”

func main() {

var t C.struct_t

var s = “hello world”

var ch *C.char

var tmp *C.char

// 分配空间, 并判断是否分配成功

t.s  = (*C.char)(C.malloc(C.size_t(100)))

if t.s == nil {

//if t.s == (*C.char)(unsafe.Pointer(uintptr(0))) {

panic(“malloc failed!\n”)

}

// 释放内存

defer C.free(unsafe.Pointer(t.s))

// 将go的字符串转为c的字符串,并自动释放

ch = C.CString(s)

defer C.free(unsafe.Pointer(ch))

// 调用C的strncpy函数复制

C.strncpy(t.s, ch, C.size_t(len(s)))

// C的指针操作

for i := C.size_t(0); i < C.strlen(t.s); i ++ {

tmp = (*C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(t.s)) + uintptr(i)))

*tmp = C.char(C.toupper(C.int(*tmp)))

}

fmt.Printf(“%s\n”, C.GoString(t.s))

fmt.Printf(“sizeof struct t is %v\n”, unsafe.Sizeof(t))

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值