为了代码清洁,我希望将我的自动生成的ctypes包装器与我的c-structure分开,与我的仅使用Python的扩展(具有其他辅助函数等)。
我无法将我的子类结构传递给我自动生成的绑定。有没有办法做到这一点?
// 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
从我的绑定创建一个子类,并尝试传递给我的func:
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
有没有办法在不修改自动生成的绑定或“猴子修补”的情况下执行此操作?
答案 0 :(得分:1)
根据评论中的要求,以下是使用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))