Python 2和3之间的ctypes差异

时间:2011-08-31 11:28:09

标签: python dll numpy python-3.x ctypes

我有一个调用DLL的python 2.7程序。我试图将脚本移植到python 3.2。 DLL调用似乎有效(即调用时没有错误),但返回的数据没有意义。

以防它可能有用: - 调用有三个参数:两个int(输入)和一个指向ushort数组(输出)的指针。

我尝试过使用python和numpy数组都没有成功。

任何人都可以列举Python 2.7和3.2之间关于ctypes的区别吗?

提前致谢

修改

以下是一些示例代码。 DLL是propietary所以我没有代码。但我确实有C标题:

void example (int width, int height, unsigned short* pointer)

python代码是:

width, height = 40, 100
imagearray = np.zeros((width,height), dtype=np.dtype(np.ushort))
image = np.ascontiguousarray(imagearray)
ptrimage = image.ctypes.data_as(ct.POINTER(ct.c_ushort))
DLL.example(width, height, ptrimage)

这适用于python 2.7但不适用于3.2。

编辑2

如果ctypes中的更改只是Cedric指出的那些,那么python 3.2不起作用是没有意义的。所以再看一下代码,我发现在我提到的函数之前有一个调用的准备函数。签名是:

void prepare(char *table)

在python中,我打电话给:

table = str(aNumber)
DLL.prepare(table)

问题是否可能是由于Python字符串处理的变化引起的?

3 个答案:

答案 0 :(得分:20)

在Python 2.7中,字符串默认为字节字符串。在Python 3.x中,默认情况下它们是unicode。在将字符串传递给.encode('ascii')之前,尝试使用DLL.prepare明确地将字符串作为字节字符串。

修改

#another way of saying table=str(aNumber).encode('ascii')
table = bytes(str(aNumber), 'ascii')
DLL.prepare(table)

答案 1 :(得分:1)

在我们的例子中,我们的代码如下:

addr = clib.some_function()
data = some_struct.from_address(addr)

这在python 2中有效,但在python 3中无效。其原因不是ctypes的任何差异,而是内存布局的变化,从而掩盖了上面代码中的错误。在python 2中,返回的地址总是(偶然)足够小以适合C int(32位),这是所有ctypes函数调用的默认返回类型。在python 3中,地址几乎总是太大,这导致指针地址被强制转换为int时损坏。

解决方案是将函数restype设置为64位整数类型,以确保它可以容纳整个地址,例如:

clib.some_function.restype = c_longlong

或:

clib.some_function.restype = POINTER(some_struct)

答案 2 :(得分:0)

根据python文档,2.7和3.2之间的唯一变化is here

  

新类型,ctypes.c_ssize_t表示C ssize_t数据类型。

在2.7中,还有其他modifications introduced

  

ctypes模块现在总是将None转换为C NULL指针   声明为指针的参数。 (由托马斯海勒改变;问题   4606.)底层的libffi库已更新为版本   3.0.9,包含针对不同平台的各种修复程序。 (更新时间   马蒂亚斯克洛斯;问题8142。)

我不确定它会解释你问题的原因......