我有一个可以使用的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 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)
在我们的案例中,我们的代码看起来像。
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)