我有一个调用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字符串处理的变化引起的?
答案 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。)
我不确定它会解释你问题的原因......