gpt4 book ai didi

go - 正确的 Go 类型传递给 C 函数?

转载 作者:IT王子 更新时间:2023-10-29 01:43:02 26 4
gpt4 key购买 nike

我正在将我用 C 编写的一些服务器代码移植到 Go,它使用了一个我真的不想重写的加密库。相反,我正在尝试使用 Cgo 编写包装器,以便我的其余代码可以更轻松地调用它。这是 lib header 的一部分:

// encryption/encryption.h
#define CRYPT_BBCFG 1

typedef struct {
// ...bunch of fields...
uint32_t bb_posn;
} CRYPT_SETUP;

int CRYPT_CreateKeys(CRYPT_SETUP* cs, void* key, unsigned char type);

下面是我尝试开始工作的概念验证片段:

package goserv

//#include "encryption/encryption.h"
import "C"

func main() {
cdata := new(C.struct_CRYPT_SETUP)
key := make([]byte, 48)
C.CRYPT_CreateKeys(cdata, &key, C.CRYPT_BLUEBURST)
}

我在 header 中定义了一个测试函数 (int test() { return 1; }) 并且从我的代码中调用它没有问题(通过 C.test()) 也没有引用任何#defined 常量 (C.CRYPT_BBCFG),但是当我尝试运行 go install goserv 时出现以下错误:

Undefined symbols for architecture x86_64:
"_CRYPT_CreateKeys", referenced from:
__cgo_e89359206bf1_Cfunc_CRYPT_CreateKeys in goserv.cgo2.o
(maybe you meant: __cgo_e89359206bf1_Cfunc_CRYPT_CreateKeys)
ld: symbol(s) not found for architecture x86_64

在这一点上,我假设我只是没有使用正确的参数调用函数。我的印象是 cdata 是 *C.struct_CRYPT_SETUP 类型,key 应该是 *byte(尽管没有 & 也不能工作)和 C.CRYPT_BLUEBURST类型...的东西。尝试 C.uchar(CRYPT_BLURBURST) 也没有任何改变。

关于编译此代码有什么建议吗?

编辑:忘了我的平台,我正在运行 Mac OS X 10.10

Edit2(已解决):Jsor 关于将 unsafe.Pointer 与 key 的第一个元素的地址一起使用的观点有所帮助,但我还必须将我的 C 源文件移动到与我的 Go 文件相同的目录中。使用 C.struct_CRYPT_DATA 而不是 C.CRYPT_DATA 会导致另一种类型错误,所以如果其他人遇到这样的错误:

./goserv.go:18: cannot use cdata (type *C.struct_CRYPT_SETUP) as type *C.struct___0 in argument to _Cfunc_CRYPT_CreateKeys

然后删除 struct_ 前缀(尽管 cgo 文档说这是直接引用 C 结构类型的方法)

最佳答案

您可能需要 &key[0],否则您将指向 Slice Header ,这是一个包含 3 个值的结构。您最终得到一个指向缓冲区指针的指针,这可能不是您想要的。

一般来说,指向 slice 后备缓冲区的指针是&slice[0],而不是&slice

作为标准免责声明:警告将 Go 分配的缓冲区传递给 C。几乎每个人都这样做,(包括我)但它 may not be a good idea, and may stop being supported at some point .这可能没问题,只要您在数据在 C 中的整个持续时间内保持对数据的引用,并且不存储指针供以后在 C 端使用,但您可能会结束由于 Go 1.3 stack moving GC 引起的奇怪现象。

更新:我刚刚记起来的东西 -- C 中的 void* 类似于 Go 的 unsafe.Pointer。所以你的电话应该是:

C.CRYPT_CreateKeys(cdata, unsafe.Pointer(&key[0]), C.CRYPT_BLUEBURST)

另一个问题可能是您是否经常使用 -l 链接外部库。为此,使用

// #cgo LDFLAGS: -llibname

import "C" 正上方的区域中,您可以在其中进行包含。

Edit2:另外,仔细观察,函数 CRYPT_CreateKeys 似乎没有在头文件中定义——只有函数原型(prototype)。确保它是否在单独的 .c 文件中定义以将其声明为 extern。不这样做绊倒 Go。

关于go - 正确的 Go 类型传递给 C 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26772100/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com