2010-01-20 2 views
16

Я новичок в Cython, и я пытаюсь использовать Cython для упаковки статической библиотеки C/C++. Я сделал простой пример следующим образом.Wrap C++ lib с Cython

test.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; 
} 

Тогда я использовал г ++ для компиляции и построить его.

g++ -c test.cpp -o libtest.o 
ar rcs libtest.a libtest.o 

Итак, теперь у меня есть статическая библиотека под названием 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 
) 

я назвал:

python setup.py build_ext --compiler=mingw32 --inplace 

Выход был:

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 
[email protected] --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 

Я также пытался использовать библиотеки = ['test'] вместо библиотек = ['libtest']. Это дало мне те же ошибки.

Любые подсказки о тех?

Спасибо!

ответ

2

Я думаю, что вы можете решить эту конкретную проблему, указав право library_dirs (где вы на самом деле положить libtest.a - по-видимому, это не становится найдено), но я думаю, что тогда вы будете иметь еще одну проблему - ввод точки не указаны должным образом как extern "C", поэтому имена функций будут «искалечены» компилятором C++ (посмотрите на имена, экспортированные из вашего libtest.a, и вы увидите!), поэтому любой другой язык, кроме C++ (включая C , Cython и т. Д.) Будут возникать проблемы с ними. Исправление состоит в том, чтобы объявить их как extern "C".

+0

Где я могу объявить extern «C»?Однако я думаю, что проблема в том, что сборка жалуется, что она не может найти libtest.a вместо одной из функций, то есть add() или mulitpy(). Поэтому я не уверен, что это сработает. Это довольно странно для меня, что он жаловался, что libtest.a не существует в 'build \ temp.win32-2.6 \ Release'. Разве это не папка сборки, созданная самим Cython? Почему Киттон попытался найти libtest.a там? –

+0

'extern 'C' 'идет в объявлениях функций в' .h', и, как я уже сказал, это следующая проблема, с которой вы столкнетесь после исправления некорректных 'library_dirs' (вы говорите, что библиотеки« находятся в текущем каталоге «и« Release »- это текущий каталог в момент, когда компилятор/компоновщик ищет библиотеку). –

23

Если код вашей C++ используется только обертку, другой вариант, чтобы установка скомпилировать файл .cpp, как это:

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 
) 

Для ссылки на статическую библиотеку, вы должны использовать extra_objects аргументом в вашем 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 
) 
+1

Нет, я сделал test.cpp только для тестирования. В реальном проекте у меня есть только файл главы и статическая библиотека. –

+3

Кажется, что вы хотите, это опция «extra_objects», отредактированный ответ. –

+0

@zyq Итак, как мы будем продолжать работу после создания файла .so? – PascalVKooten

4

Ваш файл Test.pyx не делать то, что вы ожидаете. Строка print add(2,3)не будет вызовет функцию add() C++; вы должны явно создать для этого функцию-обертку. Cython автоматически не создает обертки.

Нечто подобное, вероятно, что вы хотите:

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) 

Вы можете посмотреть на Cython-х documentation для более подробной информации.