Python正在向C函数传递32位指针地址

2024-04-26 13:29:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我想从Python脚本调用共享库中的C函数。当传递指针时,64位地址似乎在被调用函数中被截断为32位地址。Python和我的库都是64位的。在

下面的示例代码演示了该问题。Python脚本打印传递给C函数的数据的地址。然后,从被调用的C函数中打印接收到的地址。另外,C函数通过打印本地创建内存的大小和地址来证明它是64位的。如果指针以任何其他方式使用,则结果为segfault。在

CMakeLists.txt文件

cmake_minimum_required (VERSION 2.6) 
add_library(plate MODULE plate.c)

板c

^{pr2}$

测试_板材.py

import numpy
import scipy
import ctypes

N = 3
x = numpy.ones(N, dtype=numpy.float32)
y = numpy.ones(N, dtype=numpy.float32)
plate = ctypes.cdll.LoadLibrary('libplate.so')

print 'passing address: %0x' % x.ctypes.data
plate.plate(x.ctypes.data, y.ctypes.data, ctypes.c_int(N))

python-2.7的输出

In [1]: run ../test_plate.py

passing address: 7f9a09b02320

passed address: 0x9b02320

local pointer size: 8

local pointer address: 0x7f9a0949a400


Tags: 函数pyimportnumpy脚本dataaddress地址
3条回答

Python的PyIntObject在内部使用一个C long,在大多数64位平台(不包括64位Windows)上是64位的。但是,ctypes将转换后的结果赋给pa->value.i,其中value是并集,i字段是32位{}。有关详细信息,请参见Modules/_ctypes/callproc.c中的ConvParam,第588-607和645-664行。ctypes是在Windows上开发的,其中long总是32位的,但是我不知道为什么没有改为使用long字段,即pa->value.l。也许,在大多数情况下,默认创建一个C int,而不是使用long的全部范围。在

{6}这意味着你不能创建一个64位的Python指针。必须显式地创建ctypes指针。你有很多选择。如果不关心类型安全,NumPy数组最简单的选择是使用它的ctypes属性。这定义了钩子_as_parameter_,它允许Python对象设置它们在ctypes函数调用中的转换方式(参见前面链接中的第707-719行)。在本例中,它创建一个void *。例如,您可以这样调用plate

plate.plate(x.ctypes, y.ctypes, N)

但是,这并没有提供任何类型安全性来防止函数被错误类型的数组调用,这将导致无意义、错误或分段错误。^{a2解决了这个问题。这将创建一个自定义类型,可用于设置ctypes函数指针的argtypes和{}。此类型可以验证数组的数据类型、维数、形状和标志。例如:

^{pr2}$

如果不告诉ctypes参数是什么类型,它会尝试从传递给函数的值中推断参数。这个推论并不总是如你所愿。在

建议的处理方法是设置函数的^{}属性,然后显式地告诉ctypes参数类型是什么。在

plate.plate.argtypes = [
    ctypes.POINTER(ctypes.c_float), 
    ctypes.POINTER(ctypes.c_float), 
    ctypes.c_int
]

然后可以像这样调用函数:

^{pr2}$

问题是ctypes模块没有检查您试图调用的函数的函数签名。相反,它将C类型基于Python类型,因此这行代码。。。在

plate.plate(x.ctypes.data, y.ctypes.data, ctypes.c_int(N))

…正在将前两个参数作为整数传递。请参阅eryksun的答案,了解它们被截断为32位的原因。在

为了避免截短,您需要告诉ctypes这些参数实际上是带有以下内容的指针。。。在

^{pr2}$

…尽管它们实际上是指向的指针是另一回事-它们可能不是C代码假定的指向float的指针。在


更新

eryksun已经为这个问题中的特定于numpy的例子给出了一个更完整的答案,但是我将把它留在这里,因为对于使用numpy之外的东西的程序员来说,它在指针截断的一般情况下可能很有用。在

相关问题 更多 >