Python 2和3之间ctypes的区别

问题描述 投票:15回答:3

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

以防万一:- 调用需要三个参数:两个int(输入)和一个ushort数组的指针(输出)。

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

谁能列举一下Python 2.7和3.2在ctypes方面的区别?

先谢谢你

编辑

下面是一些示例代码。DLL是私有的,所以我没有代码。但我有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中不能用。

EDIT 2

如果ctypes的变化仅仅是Cedric指出的那些,那么python 3.2就不能用了,这是说不通的。所以再看代码,我发现在我提到的函数之前,有一个准备函数被调用。签名是

void prepare(char *table)

在python中,我调用的是by。

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

会不会是Python字符串处理方式的改变导致的问题?

python dll numpy python-3.x ctypes
3个回答
21
投票

在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
投票

根据python文档,2.7和3.2之间唯一的变化是 是这里

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

在 2.7 中,有一些其他的 引入的修改 :

对于声明为指针的参数,ctypes 模块现在总是将 None 转换为 C NULL 指针。(由Thomas Heller修改;问题4606.) 底层的libffi库已经更新到3.0.9版本,包含了针对不同平台的各种修复。(由 Matthias Klose 更新;问题 8142.)

我不确定这是否能解释你的问题原因......


1
投票

在我们的案例中,我们的代码看起来像。

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

原因并不是ctypes的不同,而是内存布局的改变,这揭示了上面代码中的一个bug。在python 2中,返回的地址总是(偶然)小到足以容纳一个C int(32位),这是所有ctypes函数调用的默认返回类型。在python 3中,地址几乎总是太大,这导致指针地址被胁迫为int时变得损坏。

解决办法是将函数 restype 为64位整数类型,以确保它能容纳整个地址,比如。

clib.some_function.restype = c_longlong

or:

clib.some_function.restype = POINTER(some_struct)
© www.soinside.com 2019 - 2024. All rights reserved.