2010-01-20 15 views
16

Ich bin neu in Cython und ich versuche Cython zu verwenden, um eine C/C++ statische Bibliothek zu wickeln. Ich habe ein einfaches Beispiel wie folgt gemacht.Wrap C++ - Lib mit 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; 
} 

Dann habe ich g ++, es zu kompilieren und zu bauen.

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

So jetzt habe ich eine statische Bibliothek namens 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 
) 

Die ich rief:

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

Der Ausgang war:

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 

Ich habe auch versucht, Bibliotheken = ['Test'] anstelle von Bibliotheken = ['libtest'] zu verwenden. Es gab mir die gleichen Fehler.

Irgendwelche Hinweise auf diese?

Danke!

Antwort

2

Ich denke, man kann dieses spezielle Problem beheben, indem Sie die richtige Angabe library_dirs (wo man tatsächlich libtest.a setzen - anscheinend ist es nicht gefunden zu werden), aber ich denke, dann werden Sie ein anderes Problem - Ihr Eintrag Punkte werden nicht korrekt als extern "C" deklariert, so dass die Namen der Funktion vom C++ - Compiler "gemangelt" wurden (siehe die exportierten Namen aus Ihrer libtest.a und Sie werden sehen!), also jede andere Sprache außer C++ (einschließlich C , Cython, etc) wird Probleme haben, an ihnen zu kommen. Die Fehlerbehebung besteht darin, sie als extern "C" zu deklarieren.

+0

Wo soll ich extern "C" deklarieren?Allerdings denke ich, das Problem ist jetzt, dass der Build klagt, dass er libtest.a statt einer der Funktionen, d. H. Add() oder multipy(), nicht finden kann. Ich bin mir also nicht sicher, ob das funktioniert. Es ist ziemlich komisch für mich, dass es beschwert hat, dass es keine libtest.a in 'build \ temp.win32-2.6 \ Release' gibt. Ist das nicht der Build-Ordner, der von Cython selbst generiert wird? Warum hat Cython versucht, dort nach dem libbtest.a zu suchen? –

+0

'extern" C "geht in den Deklarationen der Funktionen in der' .h', und wie ich schon sagte, das ist das nächste Problem, das Sie konfrontiert werden, nachdem Sie die falschen 'library_dirs' (Sie sagen Bibliotheken sind" im aktuellen Verzeichnis "und das' Release' ist zufällig das aktuelle Verzeichnis zu dem Zeitpunkt, zu dem der Compiler/Linker nach der Bibliothek sucht. " –

23

Wenn Ihr C++ Code nur vom Wrapper verwendet wird, ist eine weitere Option die Einrichtung Ihrer CPP-Datei zusammenstellen zu lassen, wie folgt aus:

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 
) 

zu einer statischen Bibliothek Zur Verknüpfung Sie die extra_objects verwenden Argument in Ihrem 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

Nein, ich habe "test.cpp" nur zum Testen erstellt. Im realen Projekt habe ich nur eine Kopfdatei und eine statische Bibliothek. –

+3

Es scheint, als ob Sie die 'extra_objects' Option, bearbeitete Antwort, wünschen. –

+0

@zyq Wie gehen wir weiter, sobald die .so-Datei erstellt wurde? – PascalVKooten

4

Ihre Test.pyx Datei ist nicht zu tun, was Sie erwarten. Die print add(2,3) Linie wird nicht rufen Sie die add() C++ - Funktion; Sie müssen dafür explizit eine Wrapper-Funktion erstellen. Cython erstellt keine Wrapper für Sie automatisch.

So etwas ist wahrscheinlich das, was Sie wollen:

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) 

Sie bei Cython der documentation, um weitere Informationen suchen.