设置了restype
,python 返回long
而不是c_void_p
似乎很奇怪。
例如;
# python code
from ctypes import *
dll = windll.LoadLibrary("my.dll")
dll.my_object_create.restype = c_void_p
x = dll.my_object_create()
print type(x) # prints <type 'long'>
//c++ code
my_object *my_object_create() { return new my_object(); }
void my_object_destroy(my_object *obj) { delete obj; }
我最近不得不修复一个错误,即x
反馈给另一个 ctypes 函数,指针被践踏。 此问题已通过将初始 dll 调用更改为
x = c_void_p(dll.my_object_create())
。我猜在某行的某个地方,ctypes x
被视为 4 字节长而不是 8(64 位架构(。
所以我想知道现有行为是否有什么原因导致你进入这个陷阱?
'P' 指针类型的P_get
使用 PyLong_FromVoidPtr
.如果地址适合平台long
,则返回一个 Python int
;否则,它将返回一个具有可变精度的 Python long
。这很好,但是当将此整数值作为参数传递时,默认行为是转换为 C int
,在所有受支持的平台上都是 32 位。
我认为最好的解决方案是设置argtypes
以正确将参数转换为指针类型。另一种选择是将restype
设置为 c_void_p
的子类。使用子类将禁用转换为 Python 整数。 GetResult
通过调用 _ctypes_simple_instance
来检查这一点,它实际上返回与其名称和源注释建议的相反的内容。(在 2.5 中,这个函数被命名为 IsSimpleSubType
,当时的源注释也是错误的。所讨论的"简单"从来都不是元类PyCSimpleType
,而是基类型_SimpleCData
。
POSIX:
# Configure the interpreter to load visible extension-
# module symbols, such as _ctypes_simple_instance,
# into the global symbol table.
import sys, DLFCN
sys.setdlopenflags((sys.getdlopenflags() & ~DLFCN.RTLD_LOCAL) |
DLFCN.RTLD_GLOBAL)
from ctypes import *
_ctypes_simple_instance = PyDLL(None)._ctypes_simple_instance
_ctypes_simple_instance.argtypes = py_object,
malloc = CDLL(None).malloc
class my_void_p(c_void_p):
pass
>>> _ctypes_simple_instance(c_void_p)
0
>>> _ctypes_simple_instance(my_void_p)
1
>>> malloc.restype = c_void_p
>>> type(malloc(100))
<type 'int'>
>>> malloc.restype = my_void_p
>>> type(malloc(100))
<class '__main__.my_void_p'>
窗户:
_ctypes_simple_instance
不是由 _ctypes.pyd 导出的。
from ctypes import *
malloc = cdll.msvcrt.malloc
class my_void_p(c_void_p):
pass
>>> malloc.restype = c_void_p
>>> type(malloc(100))
<class 'int'>
>>> malloc.restype = my_void_p
>>> type(malloc(100))
<class '__main__.my_void_p'>