传递继承自ctypes.Structure的类的子类

时间:2016-06-13 22:55:11

标签: python ctypes

为了代码清洁,我希望将我的自动生成的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

有没有办法在不修改自动生成的绑定或“猴子修补”的情况下执行此操作?

1 个答案:

答案 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))