Получение адреса пользовательского типа данных в C из Python с использованием ctypes

У меня есть vector структура в C со следующими полями,

 struct vector { unsigned char* data; unsigned long size; unsigned long elemsize; unsigned long capacity; }; 

и есть несколько функций, которые соответственно действуют на vector экземпляры, такие как:

 struct vector* vector_new(unsigned long elemsize); void vector_delete(struct vector* vec); void vector_push_back(struct vector* vec, void* value, unsigned long elemsize); void vector_reserve(struct vector* vec, unsigned long cap); ... 

и т. д. (имитируя стиль c ++ std::vector ).

В других разделах моей базы кода у меня есть составные структуры, например mirror :

 struct mirror { double R; double T; // extra fields omitted - see mirror_wrapper.py below struct vector* input[2]; // [vector*, vector*] struct vector* output[2]; // [vector*, vector*] }; 

который, среди прочего, имеет следующие методы,

 struct mirror* mirror_alloc(); int mirror_init(double R, double T, struct mirror* mrr); // ibn is the "initial-beam-number" void mirror_set_left_input(struct vector** input, unsigned long ibn, struct mirror* mrr); void mirror_set_right_input(struct vector** input, unsigned long ibn, struct mirror* mrr); 

где один передает адрес output поля других компонентов этим методам set_input чтобы «подключить» их.

Поля input и output каждого компонента всегда хранят экземпляры struct beam – тип данных, который просто хранит double complex поле и double поле.


В настоящее время я нахожусь в создании оболочек в Python (3.5) для вызова различных методов в объектно-ориентированном использовании позже для упрощения построения и т. Д .; используя ctypes для создания общей библиотеки кода C.

Ниже приведены обертки, которые у меня есть до сих пор,

vector_wrapper.py

 from ctypes import cdll from ctypes import Structure from ctypes import c_ubyte from ctypes import c_ulong from ctypes import POINTER class Vector(structure): _fields_ = [ ("data", POINTER(c_ubyte)), ("size", c_ulong), ("elemsize", c_ulong), ("capacity", c_ulong)] 

mirror_wrapper.py

 from ctypes import cdll from ctypes import Structure from ctypes import byref from ctypes import c_double from ctypes import c_ubyte from ctypes import c_ulong from ctypes import c_bool from ctypes import POINTER from ctypes import pointer from vector_wrapper import Vector lib = cdll.LoadLibrary('./ctn_lib.so') class Mirror(Structure): _fields_ = [ ("R", c_double), ("T", c_double), ("pR", c_double), ("pT", c_double), ("tuning", c_double), ("mass", POINTER(c_double)), ("last_time", c_double), ("net_force", c_double), ("dfcoeff", c_double), ("phfcoeff", c_double*2), #phfcoeff is a double complex in c code ("rpfcoeff", c_double), ("input", POINTER(Vector)*2), ("output", POINTER(Vector)*2), ("has_left_input", c_bool), ("has_right_input", c_bool)] 

Есть ли способ, по которому я могу получить адрес output поля какого-либо компонента (скажем, mirror ), который имеет тип struct vector** , и передать это, например, некоторой функции Mirror.set_left_input в качестве input параметра?

Кроме того, я предполагаю, что необходимо создать все поля в _fields_ структуры python, соответствующие полям в C-структурах, т. _fields_ Можно ли опустить некоторые поля из этого дескриптора или нет?

    Есть ли способ, по которому я могу получить адрес выходного поля какого-либо компонента (скажем, зеркала), который имеет тип struct vector **, и передать это, например, некоторой функции Mirror.set_left_input в качестве входного параметра?

    Чтобы получить доступ к выходному компоненту Mirror с учетом ваших структур:

     >>> m = Mirror() >>> m.output[0] <__main__.LP_Vector object at 0x00000199607CA0C8> 

    Чтобы передать его функции по ссылке:

     >>> mirror_set_left_input(byref(m.output[0]),...) 

    Кроме того, я предполагаю, что необходимо создать все поля в полях структуры python, соответствующие полям в C-структурах, т. Е. Можно ли опустить некоторые поля из этого дескриптора или нет?

    Нет, вы не можете опустить поля из определения вашей структуры, или двоичный макет базовой структуры C будет неправильным.