Python 2 和 3 之间 ctypes 的差异

Posted

技术标签:

【中文标题】Python 2 和 3 之间 ctypes 的差异【英文标题】:Differences in ctypes between Python 2 and 3 【发布时间】:2011-11-07 13:10:51 【问题描述】:

我有一个调用 DLL 的工作 python 2.7 程序。我正在尝试将脚本移植到 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 中无效。

编辑 2

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

void prepare(char *table)

在 python 中,我通过以下方式调用:

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

有没有可能是因为 Python 字符串处理的改变造成的?

【问题讨论】:

我完全不知道有什么不同。我想我们需要看看一些代码。 【参考方案1】:

在 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)

【讨论】:

几年过去了,这个答案很有用!我还遇到了一个问题,我在 Python3 中使用了一个旧的 python 库,并且无法理解为什么代码不起作用。将传递给共享库的字符串更改为 ascii 后,一切正常!【参考方案2】:

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

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)

【讨论】:

【参考方案3】:

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

一种新类型,ctypes.c_ssize_t 代表 C ssize_t 数据类型。

在 2.7 中,还有一些其他的 modifications introduced :

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

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

【讨论】:

以上是关于Python 2 和 3 之间 ctypes 的差异的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 ctypes 将(非空)列表从 Python 传递到 C++?

[微软]有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小_利用排列组合思路解决_python版

Python 3.x ctype c_wchar_p 和 c_char_p 返回状态不同于 ctypes doc

d3 = {** d1,** d2}`和`d4 = dict(** d1,** d2)之间的差?

Leetcode刷题Python376. 摆动序列

如何通过Period类计算两个日期的差?