После этого вопроса , где я пытался использовать C ++ DLL с Cython
, с учебником, подходящим для моего случая, который никогда не работал, я решил использовать ctypes
.Теперь я успешно вызываю интересующую меня функцию в моей DLL с использованием ctypes благодаря интенсивному просмотру SO.Теперь я столкнулся с проблемой использования результатов, представляющих собой массив struct в Python.
Эта функция C выглядит следующим образом:
void myfun(
double a,
//...more double parameters
int max_iter,
int * nb_iter,
myStruct * res_arr,
bool * ok
);
с myStruct
, определенным следующим образом:
typedef struct {
double dat;
int k;
int m;
// ... more int
double b;
double v;
//...more double
} myStruct;
Я вызываю эту функцию через следующий код Python:
import ctypes
lib = ctypes.CDLL('PATH_TO_DLL\\lib.dll')
myFunPy = getattr(lib,"?myFun@@YANNNNN_BUNCH_OF_Ns_NNNHPEAHPEAUmyStruct@@PEA_N@Z") # name found through dumpbin.exe (due to C++)
class myStruct(ctypes.Structure):
_fields_ = [("k", ctypes.c_int),
("m", ctypes.c_int),
#...more int parameters
("b", ctypes.c_double),
("v", ctypes.c_double)
#...more double parameters
]
myFunPy.argtypes = [ctypes.c_double,
// ... more double parameters
ctypes.c_int,
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(myStruct),
ctypes.POINTER(ctypes.c_bool)]
myFunPy.restype = ctypes.c_void_p
max_iter = 10000
a = ctypes.c_double(0.1)
// ... more double parameters definitions
nb_iter = ctypes.c_int(0) # value doesn't matter, it is initialized in myFun
ok = ctypes.c_bool(True)
res_arr = (myStruct * max_iter)()
myFunPy(a, ..., max_iter, ctypes.byref(nb_iter), res_arr, ctypes.byref(ok))
Теперь myFun
изменяет res_arr
, который является массивом структуры, как видно из приведенного выше кода,Это точно
<__main__.myStruct_Array_10000 at 0x97966c8>)
после кода, показанного выше, но я не могу понять, как преобразовать его в массив NumPy для будущего использования эффективно .
Конечно, ямог бы делать циклы с такими вещами, как for field, _ in struct._fields_
, как показано здесь , но это не главное, поскольку я использую DLL для ускорения вычислений (я действительно видел разницу во времени выполнения).res_arr
имеет размер от 200 кб до 1 Мб и содержит десятки тысяч строк и несколько десятков столбцов, поэтому я уверен, что есть способ не проходить все это с помощью циклов, но я не могу понять,как это сделать красиво.
Кажется, что если бы это был не массив struct, это было бы проще.Есть a несколько SO вопросов (также здесь , здесь , здесь и здесь ) близко к этому предмету, но речь идет либо о преобразовании просто структуры, просто массива, или чего-то близкого, но никогда не похожего на меня, и мне не удалось приспособитьрешения, так что, возможно, есть способ основать ответ на этом, но в любом случае я весь слух.