#python #c #ctypes
Вопрос:
Я пытаюсь преобразовать файл .cpp в .py, используя библиотеку ctypes.
Некоторые базовые операции работают, но я испытываю трудности при использовании структур typedef, а также malloc/free.
Вот что у меня есть:
модуль.h:
typedef struct
{
CHAR8 name[M_MODNAMELEN_A]; /**< Name of the module. */
} MODULE_NAME;
typedef struct
{
UINT16 countModules; /**< Count of module names.*/
MODULE_NAME * names; /**< Array of module names. */
} MODULE_LIST;
program.cpp:
UINT16 countModules;
SINT32 ret = GetCountModules(targetHandle, amp;countModules);
if(ret!=M1C_OK)
return ret;
MODULE_LIST modList;
modList.names = (MODULE_NAME*)malloc(countModules * sizeof(MODULE_NAME));
// do some calculations
free( modList.names );
program.py:
from ctypes import *
c_lib = CDLL('libXXYY.so')
class MODULE_NAME(Structure):
_fields_ = [
('name', c_byte)
]
def __repr__(self):
return '({0})'.format(self.name)
class MODULE_LIST(Structure):
_fields_ = [
('countModules', c_uint),
('names', POINTER(MODULE_NAME)) ### Is this conversion correct?
]
def __repr__(self):
return '({0}, {1})'.format(self.x, self.y)
count_modules = c_uint()
ret = c_long(c_lib.GetCountModules(target_handle, byref(count_modules)))
if ret.value != M1C_OK:
return ret
# Up to here everything works fine..
# Allocating memory for the list of module names
modList = MODULE_LIST()
modList.names = ### How to convert the malloc line?
## Some calcs
### How to convert the free( modList.names ); line?
Python работает нормально до строки «modList.names=».. Там я попробовал несколько вещей (например: modList.names = (ИМЯ_МОДУЛЯ)count_modules.value * sizeof(ИМЯ_МОДУЛЯ ())), но все мои попытки не увенчались успехом.
Как мне перевести строку malloc с cpp на python?
Как мне перевести свободную строку с cpp на python?
Являются ли переводы структуры typedef в класс правильными? Особенно один из «MODULE_LIST».
Ответ №1:
Как мне перевести строку malloc с cpp на python?
Обычно библиотека DLL, которая возвращает что-то вроде MODULE_LIST, выполняет за вас malloc и предоставляет функцию, чтобы освободить ее позже, но если вам нужно заполнить ее самостоятельно, тип массива создается путем умножения типа на размер, а затем вызывает его для создания экземпляра:
m = MODULE_LIST()
m.countModules = countModules
m.names = (MODULE_NAME * countModules)() # create instance of array
Как мне перевести свободную строку с cpp на python?
Если выделено, как указано выше, Python освободит его, когда больше не будет ссылок на память, например, когда m
выше выходит за рамки. Вы можете вызвать del m
явное разыменование памяти. Если m
это единственная ссылка, она будет освобождена.
Являются ли переводы структуры typedef в класс правильными? Особенно один из «MODULE_LIST».
Нет, CHAR8 name[M_MODNAMELEN_A];
это массив, поэтому умножьте тип на длину, чтобы получить правильный тип массива:
M_MODNAMELEN_A = 100 # some constant that wasn't defined by OP
class MODULE_NAME(Structure):
_fields_ = ('name',c_char * M_MODNAMELEN_A),
MODULE_LIST
имеет 16-разрядное целое число, поэтому используйте правильный 16-разрядный тип:
class MODULE_LIST(Structure):
_fields_ = (('countModules',c_uint16),
('names',POINTER(MODULE_NAME)))
Чтобы правильно вызвать функцию, рекомендуется определить .argtypes
и .restype
для функции улучшить проверку ошибок:
# Assume "int GetCountModules(HANDLE handle, UINT16* pCount)" exists in dll.
dll = CDLL('./somedll')
dll.GetCountModules.argtypes = c_void_p, POINTER(c_uint16)
dll.GetCountModules.restype = c_int
# Make an instance to the output parameter and pass it by reference:
countModules = c_uint16()
ret = dll.GetCountModules(targetHandle, byref(countModules))