python ctypes将指向结构的指针作为参数发送到本机库

时间:2012-02-03 08:59:39

标签: python pointers struct ctypes

我正在尝试在Linux中为本机库编写包装器。问题是:

c中的定义:

int mymethod(mystruct* ptr)

python中的


_lib.mymethod.argtypes = (ctypes.POINTER(mystruct),)
_lib.mymethod.restype = ctypes.c_int

s = mystruct()

_lib.mymethod(ctypes.byref(s))
引发:期望的LP_mystruct实例而不是指向mystruct的指针

_lib.mymethod(ctypes.pointer(s))
引发预期的LP_mystruct实例而不是LP_mystruct

错误。如何将结构作为指向本机方法的指针传递?

感谢。

METE

2 个答案:

答案 0 :(得分:5)

问题是来自ctypes的更高级别的“POINTER”在Python中是一个不同的对象,而不是“一般指针”(ctypes.CArgObject by ctypes.byref),它返回一个或代表一个数字一个内存地址(由ctype adrresof返回的内容) - 您可以注释您的函数以接收`ctypes.c_voidp并使用_lib.mymethod(ctypes.addressof(a))调用它 -

或者如果你想在强制类型的一方工作以避免会导致Python崩溃的错误(类型错误会引发Python异常 - 传递给C语言的错误参数会导致Python解释器本身出现分段错误),你必须创建一个变量来保存新的“类型”,它是你的结构的一个指针 - 然后用你的结构地址创建这个类型的实例:

mystruct_pointer = ctypes.POINTER(mystruct)
_lib.mymethod.argtypes = (mystruct_pointer,)
_lib.mymethod.restype = ctypes.c_int

s = mystruct()

_lib.mymethod(mystruct_pointer.from_address(ctypes.addressof(s)))

答案 1 :(得分:3)

(我知道这是一个老问题,但我认为接受的答案是一个不必要的解决方法,所以我想把这个留给后人。)

实际上ctypes应explicitly support使用byref()来传递这样的指针:

  

ctypes导出byref()函数,该函数用于通过引用传递参数。使用pointer()函数可以实现相同的效果,尽管pointer()因为它构造了一个真正的指针对象而做了很多工作,所以如果不这样做,byref()会更快需要Python本身的指针对象。

可能的原因是你已经在多个地方定义了你的结构(例如在不同的模块中) - 如果argtypes赋值看到一个定义而函数调用看到另一个定义,则会出现这个令人困惑的错误。换句话说,ctypes尝试匹配两个mystruct类型,这些类型的内容(可能)相同,并且具有完全相同的名称,但它们不是相同的类型。只要基本结构类型是单个类型对象,如果使用pointer()byref()POINTER()()构造指向它的指针并不重要 - ctypes将检测到底层(指向)类型是相同的。

要验证是否是这种情况,请在调用外部函数之前尝试assert(_lib.mymethod.argtypes[0]._type_ == type(s))