Я определил класс ctypes
и связанную с ним удобную функцию:
class BNG_FFITuple(Structure):
_fields_ = [("a", c_uint32),
("b", c_uint32)]
class BNG_FFIArray(Structure):
_fields_ = [("data", c_void_p),
("len", c_size_t)]
# Allow implicit conversions from a sequence of 32-bit unsigned ints
@classmethod
def from_param(cls, seq):
return seq if isinstance(seq, cls) else cls(seq)
def __init__(self, seq, data_type = c_float):
array_type = data_type * len(seq)
raw_seq = array_type(*seq)
self.data = cast(raw_seq, c_void_p)
self.len = len(seq)
def bng_void_array_to_tuple_list(array, _func, _args):
res = cast(array.data, POINTER(BNG_FFITuple * array.len))[0]
return res
convert = lib.convert_to_bng
convert.argtypes = (BNG_FFIArray, BNG_FFIArray)
convert.restype = BNG_FFIArray
convert.errcheck = bng_void_array_to_tuple_list
drop_array = lib.drop_array
drop_array.argtypes = (POINTER(BNG_FFIArray),)
Затем я определяю простую удобную функцию:
def f(a, b):
return [(i.a, i.b) for i in iter(convert(a, b))]
Большая часть работы работает отлично, но у меня есть две проблемы:
- Это недостаточно гибко; Я бы хотел создать экземпляр
BNG_FFITuple
с помощьюc_float
вместоc_uint32
(поэтому поляc_float
) и наоборот, поэтомуBNG_FFIArray
data_type
-c_uint32
. Однако я не знаю, как это сделать. - Я хочу освободить память, которая теперь принадлежит Python, отправив
POINTER(BNG_FFIArray)
обратно в мой dylib (см.drop_array
- я уже определил функцию в своем dylib), но я не уверен, в какой момент я должен это назвать.
Есть ли способ инкапсулировать все это более аккуратным, более путинским способом, что также безопаснее? Я обеспокоен тем, что без очистки памяти определяется надежным способом (на __exit__
? __del__
?) Что все, что пойдет не так, приведет к свободной памяти