2012-02-03 90 views
5

我想在Linux中编写一个包装到本地库。问题是这样的:python ctypes发送指针结构作为参数到本地库

定义在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代替LP_mystruct

错误

_lib.mymethod(ctypes.pointer(s))
引发预期LP_mystruct实例。如何将结构作为指针传递给本地方法?

谢谢。

METE

回答

5

的问题是,高电平“POINTER”从ctypes的是,在Python,一个不同的对象不是“通用指针”(ctypes.CArgObjectctypes.byref),其被返回或单个数字表示存储器地址(这是由CTYPE的adrresof返回) - 你可以注释你的函数接收`ctypes.c_voidp_lib.mymethod(ctypes.addressof(a)),而不是把它叫做 -

或者,如果你想在stronged类型的侧努力避免的错误,会崩溃Python(类型错误会引发Python异常 - 而不是 - 传递给C uncti的错误参数on会导致Python解释器本身出现分段错误),您必须创建一个变量来保存新的“type”,这是指向您的结构的指针 - 然后使用结构的地址创建此类型的实例:

​​
+1

谢谢!我用你说的第二种方法,它没有问题。 – mete 2012-02-03 16:14:24

+0

这里有类似的东西 - https://codexample.org/questions/238108/python-ctypes-sending-pointer-to-structure-as-parameter-to-native-library.c – 2017-09-07 07:50:42

+0

这是ctypes中更高级别的POINTER类型? – 2017-09-07 10:07:06

3

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

使用byref()传递其实ctypes的应该explicitly support一个像这样的指针:

个ctypes导出用于通过引用传递参数的byref()函数。使用pointer()函数也可以达到同样的效果,但pointer()做了很多工作,因为它构造了一个真正的指针对象,因此如果您不需要Python本身的指针对象,则使用byref()会更快。

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

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