Instead of subclassing c_void_p
, you can define the class method from_param
and instance attribute _as_parameter_
. You may not need either option if you're just proxying a C++ object that's referenced in a private attribute such as _obj
. That said, a subclass of c_void_p
can be used directly with ctypes pointers, arrays, and structs, which may be convenient in your overall design.
The following example may help:
from ctypes import *
__all__ = ['CellComplex']
class Cell(c_void_p):
def __new__(cls, *args, **kwds):
raise TypeError("cannot create %r instances" % cls.__name__)
@property
def dimension(self):
return lib.dim(self)
class CellComplex(c_void_p):
def __init__(self, p):
pair = c_double * 2
point = (pair * len(p))(*(pair(*q[:2]) for q in p))
self.value = lib.new_cellComplex(point, len(p)).value
@property
def dimension(self):
"""Wrap a function that returns size_t."""
return lib.????????(self)
def get_elements(self):
el = []
for i in range(self.dimension):
size = lib.size_elementsAtSpecifiedDim(self, i)
cells = lib.get_elementsAtSpecifiedDim(self, i)
el.append(cells[:size])
return el
Function pointer definitions:
lib = CDLL('./cellComplex_lib.so')
lib.dim.restype = c_int
lib.dim.argtypes = [Cell]
lib.new_cellComplex.restype = CellComplex
lib.new_cellComplex.argtypes = [POINTER(c_double * 2), c_size_t]
lib.size_elementsAtSpecifiedDim.restype = c_int
lib.size_elementsAtSpecifiedDim.argtypes = [CellComplex, c_int]
lib.get_elementsAtSpecifiedDim.restype = POINTER(Cell)
lib.get_elementsAtSpecifiedDim.argtypes = [CellComplex, c_int]
I separated out the function pointer definitions from the class method definitions. There's no need to redefine a function pointer's restype
and argtypes
every time a method is called. If the function returns a variably sized array, you're better off setting it to a pointer type. You can slice the result to a list or cast
to an array type.
CellComplex
is initialized by a sequence p
of floating point pairs such as [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]]
.
I eliminated the c_cellComplex
class. You can just set the instance's value
.
lib.new_cellComplex
returns an instance of CellComplex
, but ctypes bypasses __new__
and __init__
when CellComplex
is used as a restype
, so that's not an issue. It would be less twisted to instead override __new__
, but you'd still have to override c_void_p.__init__
.
The dimension
attribute needs to be a property that calls an exported function, instead of relying on static data in the Python object.