Te doy la bienvenida a proyecto on line, en este lugar vas a encontrar la resolución que buscabas.
Solución:
Incluso Cython generalmente se usa con Cpuede generar C++ código, también. Al compilar, se agrega el --cplus
bandera.
Ahora, crear un envoltorio para la clase es simple y no muy diferente de envolver una estructura. Difiere principalmente de declarar el extern
pero eso no es mucha diferencia en absoluto.
Supongamos que tienes una clase MyCppClass
en mycppclass.h
.
cdef extern from "mycppclass.h":
cppclass MyCppClass:
int some_var
MyCppClass(int, char*)
void doStuff(void*)
char* getStuff(int)
cdef class MyClass:
# the public-modifier will make the attribute public for cython,
# not for python. Maybe you need to access the internal C++ object from
# outside of the class. If not, you better declare it as private by just
# leaving out the `private` modifier.
# ---- EDIT ------
# Sorry, this statement is wrong. The `private` modifier would make it available to Python,
# so the following line would cause an error es the Pointer to MyCppClass
# couldn't be converted to a Python object.
#>> cdef public MyCppClass* cobj
# correct is:
cdef MyCppClass* obj
def __init__(self, int some_var, char* some_string):
self.cobj = new MyCppClass(some_var, some_string)
if self.cobj == NULL:
raise MemoryError('Not enough memory.')
def __del__(self):
del self.cobj
property some_var:
def __get__(self):
return self.cobj.some_var
def __set__(self, int var):
self.cobj.some_var = var
Tenga en cuenta que el new
La palabra clave solo está disponible cuando la --cplus
la bandera está configurada, de lo contrario, use malloc
desde
al exteriorizarlo.
También tenga en cuenta que no necesita desreferenciar el puntero (->
) para llamar al método. Cython rastrea el tipo de objeto y aplica lo que se ajusta.
Los archivos .pxd son para separar las declaraciones de la implementación o para evitar la colisión de espacios de nombres. Imagina que te gustaría nombrar tu Python-wrapper como la clase C++. Simplemente coloque en su archivo .pxd el extern
declaraciones y cimport
el archivo pxd en el .pyx.
cimport my_pxd
cdef my_pxd.SomeExternedType obj
Tenga en cuenta que no puede escribir implementaciones en un archivo .pxd.
Entonces, después de muchos pinchazos, prueba y error, gritos y tirones de pelo, finalmente conseguí que esto funcionara. Sin embargo, primero tuve que volver a escribir mi C++ en C, lo que para mí solo implicaba convertir todos mis std::string
variables a char*
y hacer un seguimiento de algunas longitudes.
Una vez hecho, tenía mis archivos .h y .c. Quería hacer una sola función del código C disponible en Python. Resulta que Cython puede compilar sus archivos C en la extensión por usted y vincular cualquier biblioteca de una sola vez, por lo que, comenzando con mi setup.py, terminó luciendo así:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules=[
Extension("myext",
["myext.pyx", "../stuff.c"],
libraries=["ssl", "crypto"]
)
]
setup(
name = "myext",
cmdclass = "build_ext": build_ext,
ext_modules = ext_modules
)
Como puede ver, el segundo argumento de la Extensión simplemente enumera todos los archivos que deben compilarse, Cython resuelve cómo compilarlos según su extensión de archivo, por lo que puedo decir. las bibliotecas array le dice al compilador de Cython lo que debe vincularse (en este caso, estaba envolviendo algunas cosas criptográficas que parecía que no podía imitar directamente a través de las bibliotecas de Python existentes).
Para hacer que mi función C esté disponible en el archivo .pyx, escribe un pequeño contenedor en el .pxd. Mi myext.pxd tenía el siguiente aspecto:
cdef extern from "../stuff.h":
char* myfunc(char* arg1, char* arg2, char* arg3)
En el .pyx, luego usa la declaración cimport para importar esta función, que luego está disponible para usar como si fuera cualquier otra función de Python:
cimport myext
def my_python_func(arg1, arg2, arg3):
result = myext.myfunc(arg1, arg2, arg3)
return result
Cuando construyes esto (al menos en Mac) obtienes un .para que puedas importar en python y ejecutar las funciones desde .pyx. Puede haber una forma mejor y más correcta de hacer que todo funcione, pero eso viene de la experiencia y este fue un primer encuentro que logré resolver. Estaría muy interesado en los punteros donde puedo haber ido mal.
Actualizar:
Después de seguir usando Cython, descubrí que era muy sencillo integrarlo también con C++, una vez que sabes lo que estás haciendo. Haciendo C++ string
disponible es tan simple como from libcpp.string cimport string
en tu pyx/pyd. Declarar la clase C++ es tan fácil como:
cdef extern from "MyCPPClass.h":
cdef cppclass MyCPPClass:
int foo;
string bar;
Claro, básicamente tiene que volver a declarar la definición .h de su clase en un formato Pythonic, pero ese es un pequeño precio a pagar por obtener acceso a sus funciones C++ ya escritas.
Cython es principalmente para el desarrollo de C, para integrar C ++ con Python, recomendaría Boost.Python. Su excelente documentación debería ayudarlo a comenzar bastante rápido.
Te mostramos comentarios y puntuaciones
Si guardas algún incógnita o forma de medrar nuestro división puedes realizar una crítica y con mucho placer lo interpretaremos.