天天看点

python自定义数据类型,使用ctypes从Python获取C中的自定义数据类型的地址

python自定义数据类型,使用ctypes从Python获取C中的自定义数据类型的地址

I have a vector struct in C with the following fields,

struct vector {

unsigned char* data;

unsigned long size;

unsigned long elemsize;

unsigned long capacity;

};

and there are a few functions which correspondingly act on vector instances, such as:

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);

...

and so on (mimicking a c++ style std::vector).

In other sections of my code base I have component structs, for example 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*]

};

which, amongst others, has the following methods,

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);

where one passes the address of another components' output field to these set_input methods to "connect" them.

The input and output fields of every component always store instances of struct beam - a data-type which simply stores a double complex field and a double field.

Currently I am in the process of building wrappers in Python (3.5) to call the various methods in an object-oriented to use later on for easier plotting and so forth; using ctypes to build a shared library of the C code.

The following are the wrappers that I have so far,

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)]

Is there any way in which I can get the address of an output field of some component (say a mirror), which has the type struct vector**, and pass this to, e.g., some function Mirror.set_left_input as the input parameter?

Also, I assume it is necessary to create all fields in the _fields_ of a python structure corresponding to the fields in the C structs - i.e. is it possible to omit some fields from this descriptor or not?

解决方案Is there any way in which I can get the address of an output field of some component (say a mirror), which has the type struct vector**, and pass this to, e.g., some function Mirror.set_left_input as the input parameter?

To access the output component of a Mirror given your structures:

>>> m = Mirror()

>>> m.output[0]

To pass it to a function by reference:

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

Also, I assume it is necessary to create all fields in the fields of a python structure corresponding to the fields in the C structs - i.e. is it possible to omit some fields from this descriptor or not?

No, you cannot omit fields from your structure definition, or the binary layout of the underlying C structure won't be correct.