传递继承自 ctypes.Structure 的 class 的子 class
Passing a subclass of a class that inherits from ctypes.Structure
为了代码整洁,我想让我的 c 结构自动生成的 ctypes 包装器与我的 Python-only 扩展(它有额外的辅助函数等)分开。
我无法将我的子类结构传递到我自动生成的绑定。有办法吗?
// C Code
typedef struct CStruct
{
int value;
} CStruct;
int CFunc(const CStruct **pCStruct);
自动生成的 python 绑定:
# Python Implementation
import ctypes
class PyStruct(ctypes.Structure)
_fields_ = ['value', ctypes.c_int32]
pyfunc = dll.CFunc
pyfunc.argtypes = (ctypes.POINTER(ctypes.POINTER(PyStruct)),)
pyfunc.restype = ctypes.c_int32
从我的绑定创建一个子类,并尝试传递给我的函数:
class PySubStruct(PyStruct):
def __init__(self, *args, **kwargs):
super(PySubStruct, self).__init__(*args, **kwargs)
def value_mult(self, factor):
return self.value * factor
# Works great
structptr = ctypes.pointer(PyStruct())
result_A = pyfunc(ctypes.byref(structptr))
# Create an instance of substruct and call the c-func.
# Raises exception
substructptr = ctypes.pointer(PySubStruct())
result_B = pyfunc(ctypes.byref(substructptr))
例外情况:
ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>:
expected LP_LP_PyStruct instance instead of
pointer to LP_PySubStruct
有没有办法在不修改自动生成的绑定或 "monkey-patching" 的情况下做到这一点?
根据评论中的要求,这是一个使用 ctypes.cast
:
的示例
# Python Implementation
import ctypes
class PyStruct(ctypes.Structure):
_fields_ = [('value', ctypes.c_int32)]
# Declaring a type name for simplicity
LP_LP_PyStruct = ctypes.POINTER(ctypes.POINTER(PyStruct))
pyfunc = ctypes.CDLL('x').CFunc
pyfunc.argtypes = (LP_LP_PyStruct,) # Using the typename
pyfunc.restype = ctypes.c_int32
class PySubStruct(PyStruct):
def __init__(self, *args, **kwargs):
super(PySubStruct, self).__init__(*args, **kwargs)
def value_mult(self, factor):
return self.value * factor
# Works great
structptr = ctypes.pointer(PyStruct())
result_A = pyfunc(ctypes.byref(structptr))
# Create an instance of substruct and call the c-func.
# Now works great
substructptr = ctypes.pointer(PySubStruct())
result_B = pyfunc(ctypes.cast(ctypes.byref(substructptr),LP_LP_PyStruct))
为了代码整洁,我想让我的 c 结构自动生成的 ctypes 包装器与我的 Python-only 扩展(它有额外的辅助函数等)分开。
我无法将我的子类结构传递到我自动生成的绑定。有办法吗?
// C Code
typedef struct CStruct
{
int value;
} CStruct;
int CFunc(const CStruct **pCStruct);
自动生成的 python 绑定:
# Python Implementation
import ctypes
class PyStruct(ctypes.Structure)
_fields_ = ['value', ctypes.c_int32]
pyfunc = dll.CFunc
pyfunc.argtypes = (ctypes.POINTER(ctypes.POINTER(PyStruct)),)
pyfunc.restype = ctypes.c_int32
从我的绑定创建一个子类,并尝试传递给我的函数:
class PySubStruct(PyStruct):
def __init__(self, *args, **kwargs):
super(PySubStruct, self).__init__(*args, **kwargs)
def value_mult(self, factor):
return self.value * factor
# Works great
structptr = ctypes.pointer(PyStruct())
result_A = pyfunc(ctypes.byref(structptr))
# Create an instance of substruct and call the c-func.
# Raises exception
substructptr = ctypes.pointer(PySubStruct())
result_B = pyfunc(ctypes.byref(substructptr))
例外情况:
ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>:
expected LP_LP_PyStruct instance instead of
pointer to LP_PySubStruct
有没有办法在不修改自动生成的绑定或 "monkey-patching" 的情况下做到这一点?
根据评论中的要求,这是一个使用 ctypes.cast
:
# Python Implementation
import ctypes
class PyStruct(ctypes.Structure):
_fields_ = [('value', ctypes.c_int32)]
# Declaring a type name for simplicity
LP_LP_PyStruct = ctypes.POINTER(ctypes.POINTER(PyStruct))
pyfunc = ctypes.CDLL('x').CFunc
pyfunc.argtypes = (LP_LP_PyStruct,) # Using the typename
pyfunc.restype = ctypes.c_int32
class PySubStruct(PyStruct):
def __init__(self, *args, **kwargs):
super(PySubStruct, self).__init__(*args, **kwargs)
def value_mult(self, factor):
return self.value * factor
# Works great
structptr = ctypes.pointer(PyStruct())
result_A = pyfunc(ctypes.byref(structptr))
# Create an instance of substruct and call the c-func.
# Now works great
substructptr = ctypes.pointer(PySubStruct())
result_B = pyfunc(ctypes.cast(ctypes.byref(substructptr),LP_LP_PyStruct))