python调用cgo库——32位和64位问题

问题描述

我构建了一个 cgo 库并使用 python(带有 ctypes 包)来调用它。代码被编译成 32 位和 64 位版本,这些库分别被 32 位和 64 位 python 程序调用。我发现显然参数没有正确传递。我认为这可能与如何定义数组以及如何在 python 程序和库之间传递有关。

例如go库“callnames.so”中的一个函数定义为

func Initialize(namelist []*C.char,grp *C.char)

调用这个函数的python代码部分是 类 GoSliceChar(结构): fields = [("data",POINTER(c_char_p)),("len",c_longlong),("cap",c_longlong)]

numNames = 3
n1 = c_char_p(b"peter")
n2 = c_char_p(b"tom")
n3 = c_char_p(b"nancy")
group = c_char_p(b"group1")

names = GoSliceChar((c_char_p * numComponents)(n1,n2,n3),numNames,numNames ) 


lib = cdll.LoadLibrary("./callnames.so")
lib.Initialize(names,group)

这些代码在 64 位环境下工作正常,即 python-64 + 64 位 cgo 库。但是,当我切换到 32 位时出现了问题。通过将 python 中 GoSliceChar 的定义更改为

,我进行了快速而肮脏的修复
    class GoSliceChar(Structure):
       _fields_ = [("data",c_long),c_long)] 

但是我真的不明白为什么这个问题被解决了,它是否是一个可靠的解决方案。请帮忙。谢谢。

解决方法

我对我的问题有了一些新的发现。看起来在编译 cgo 库之后,会自动生成一个 .h 文件。在这个文件中,所有的数组都定义为 GoSlice

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

对于 32 位库,GoInt 定义为

typedef GoInt32 GoInt;

而对于 64 位库,GoInt 定义为

 typedef GoInt32 GoInt; 

在我看来,在调用这些库时必须确保 python 代码能够适应这一点

class GoSliceChar(Structure):
    if is_64bit():
        _fields_ = [("data",POINTER(c_char_p)),("len",c_longlong),("cap",c_longlong)]  
    else:
        _fields_ = [("data",c_long),c_long)]

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...