J'ai une bibliothèque C (appelée clib
avec l'en-tête clib.h
) que j'appelle Ctypes
. Une fonction get_struct
renvoie un pointeur sur une structure Foo
qui est déclarée en avant dans clib.h
et que je peux utiliser pour d'autres appels de fonction en tant que pointeur (comme use_struct(Foo* foo)
). Je voudrais utiliser ce pointeur pour appeler le même code de fonction dans Cython
. Puisque je ne connais pas le contenu de la structure, je ne peux pas créer une structure en double dans Cython et copier sur les valeurs des types ctypes. Je voudrais donc plutôt créer un pointeur cython sur le même espace mémoire pour appeler du code C qui lie la même API.Transmettre la structure ctypes en cython
Le code le fait en gros.
En clib.h:
typedef struct Foo Foo;
Foo * get_struct();
void use_struct(Foo *)
Du côté python avec ctypes:
# load clib DLL
clib = ctypes.CDLL('clib.so')
# empty Ctypes declaration
class Foo_ct(ctypes.Structure):
pass
# get and use the struct
clib.get_struct.restype = ctypes.POINTER(Foo_ct)
foo_ct = clib.get_struct()
clib.use_struct(foo_ct)
# call cython code
bar(foo_ct)
Du côté Cython, en cylib.pyx:
cdef extern from "clib.h":
cdef struct Foo:
pass
void use_struct(Foo *)
cpdef bar(foo_ct):
cdef Foo* foo_cy
foo_cy = <Foo*>&foo_ct # or something equivalent
cy_use_struct(foo_cy)
Sur le Cython côté, dans cylibc.cpp:
#import "clib.h"
void cy_use_struct(Foo * foo)
{
use_struct(foo);
}
Ceci ne génère pas et renvoie des erreurs Cannot take address of Python variable
ou assigning to 'PyObject *' (aka '_object *') from incompatible type 'void'
sur la ligne foo_cy = <Foo*>&foo_ct
.
Des idées pour aller de l'avant?
Depuis 'foo_ct' est l'adresse d'un struct' Foo_ct', vous pouvez le faire 'bar (size_t foo_ct): cy_use_struct ( foo_ct) '. C'est-à-dire, obtenir l'adresse de l'objet C en python, et la renvoyer à l'objet C dans Cython –
oz1
c'est une bonne idée, mais cela me donne une erreur de segmentation .. – toine
Je ne peux pas le tester actuellement, donc je poste en tant que commentaire: Je pense que vous faites 'ctypes.addressof (foo_ct)' pour obtenir l'adresse. Convertissez cela en un entier Cython puis au pointeur. (Je suis assez sûr que la distribution en deux étapes est nécessaire) – DavidW