pyx - pyrex python
Envuelva C++ lib con Cython (3)
Creo que puede solucionar este problema específico especificando los library_dirs
correctos (donde realmente colocó libtest.a - aparentemente no se encuentra), pero creo que tendrá otro problema: sus puntos de entrada no se declaran correctamente. extern "C"
, por lo que los nombres de las funciones habrán sido "destrozados" por el compilador de C ++ (mira los nombres exportados desde libtest.a y verás!), por lo que cualquier otro idioma, excepto C ++ (incluido C, Cython, etc) tendrán problemas para llegar a ellos. La solución es declararlos como extern "C"
.
Soy nuevo en Cython y estoy tratando de usar Cython para envolver una biblioteca estática C / C ++. Hice un ejemplo simple como el siguiente.
Prueba.h:
#ifndef TEST_H
#define TEST_H
int add(int a, int b);
int multipy(int a, int b);
#endif
Test.cpp
#include "test.h"
int add(int a, int b)
{
return a+b;
}
int multipy(int a, int b)
{
return a*b;
}
Luego usé g ++ para compilarlo y construirlo.
g++ -c test.cpp -o libtest.o
ar rcs libtest.a libtest.o
Así que ahora tengo una biblioteca estática llamada libtest.a.
Test.pyx:
cdef extern from "test.h":
int add(int a,int b)
int multipy(int a,int b)
print add(2,3)
Setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension("test",
["test.pyx"],
language=''c++'',
include_dirs=[r''.''],
library_dirs=[r''.''],
libraries=[''libtest'']
)]
setup(
name = ''test'',
cmdclass = {''build_ext'': build_ext},
ext_modules = ext_modules
)
El llamé:
python setup.py build_ext --compiler=mingw32 --inplace
La salida fue:
running build_ext
cythoning test.pyx to test.cpp
building ''test'' extension
creating build
creating build/temp.win32-2.6
creating build/temp.win32-2.6/Release
C:/Program Files/pythonxy/mingw/bin/gcc.exe -mno-cygwin -mdll -O -Wall -I. -IC:/
Python26/include -IC:/Python26/PC -c test.cpp -o build/temp.win32-2.6/Release/test.o
writing build/temp.win32-2.6/Release/test.def
C:/Program Files/pythonxy/mingw/bin/g++.exe -mno-cygwin -mdll -static --entry _D
llMain@12 --output-lib build/temp.win32-2.6/Release/libtest.a --def build/temp.w
in32-2.6/Release/test.def -s build/temp.win32-2.6/Release/test.o -L. -LC:/Python
26/libs -LC:/Python26/PCbuild -ltest -lpython26 -lmsvcr90 -o test.pyd
g++: build/temp.win32-2.6/Release/libtest.a: No such file or directory
error: command ''g++'' failed with exit status 1
También intenté usar las bibliotecas = [''prueba''] en lugar de las bibliotecas = [''libtest'']. Me dio los mismos errores.
¿Alguna pista sobre eso?
¡Gracias!
Si su código de C ++ solo lo utiliza el envoltorio, otra opción es permitir que la configuración compile su archivo .cpp, como este:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension("test",
["test.pyx", "test.cpp"],
language=''c++'',
)]
setup(
name = ''test'',
cmdclass = {''build_ext'': build_ext},
ext_modules = ext_modules
)
Para enlazar a una biblioteca estática, debe usar el argumento extra_objects en su Extension
:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension("test",
["test.pyx"],
language=''c++'',
extra_objects=["libtest.a"],
)]
setup(
name = ''test'',
cmdclass = {''build_ext'': build_ext},
ext_modules = ext_modules
)
Tu archivo Test.pyx
no está haciendo lo que esperas. La línea de print add(2,3)
no llamará a la función add()
C ++; tienes que crear explícitamente una función de envoltura para hacer eso. Cython no crea envoltorios para ti automáticamente.
Algo como esto es probablemente lo que quieres:
cdef extern from "test.h":
int _add "add"(int a,int b)
int _multiply "multiply"(int a,int b)
def add(a, b):
return _add(a, b)
def multiply(a, b):
return _multiply(a, b)
print add(2, 3)
Puedes consultar la documentation de Cython para más detalles.