2013-08-01 13 views
7

Mam kilka funkcji szablonu C++ zadeklarowanych i zaimplementowanych w pliku nagłówkowym C++ i chcę uzyskać dostęp do niektórych funkcji w Cython.Wywoływanie zewnętrznych funkcji szablonu C++ w języku Cython

Załóżmy C++ kod znajduje się header.hpp następująco

template <class T> 
T doublit(T& x) { 
    return 2*x; 
} 

Co muszę napisać w pliku .pyx iw pliku setup.py tak, że mogę korzystać z funkcji w Pythonie jak

>>> import modname 
>>> print modname.doublit(3) 
6 

PS: Czy można uzyskać dostęp do tych samych funkcji w programie PYPY? A jeśli tak, to w jaki sposób?


Dzięki za pomoc. Ale mam kolejne trudności (poniżej), kiedy staram się podążać twoją drogą.

doublit.h

template <class T> 
T doublit(T& x) { 
    return 2*x; 
} 

cdoublit.pxd

cdef extern from "doublit.h": 
    cdef int doublit1 "doublit<int>"(int& foo) 
    cdef double doublit2 "doublit<double>"(double& foo) 

doublit.pyx

# main.pyx file 
from cdoublit cimport * 

cdef int n1 = 5 
cdef double n2 = 5.0 
print(doublit1(n1)) 
print(doublit2(n2)) 

i setup.py

from distutils.core import setup 
from distutils.extension import Extension 
from Cython.Distutils import build_ext 

ext_modules = [Extension("doublit", ["doublit.pyx"])] 

setup(
name = 'Learning Cython', 
cmdclass = {'build_ext': build_ext}, 
ext_modules = ext_modules 
) 

Wreszcie zbudować jako

>>> python setup.py build_ext --inplace 

ale otrzymuję następujący wyjątek:

###:doublit markma$ python setup.py build_ext --inplace 
running build_ext 
cythoning doublit.pyx to doublit.c 
building 'doublit' extension 
creating build 
creating build/temp.macosx-10.6-intel-2.7 
gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -isysroot /Developer/SDKs/MacOSX10.6.sdk -arch i386 -arch x86_64 -g -O2 -DNDEBUG -g -O3 -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c doublit.c -o build/temp.macosx-10.6-intel-2.7/doublit.o 
In file included from doublit.c:311: 
doublit.h:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘<’ token 
doublit.c: In function ‘initdoublit’: 
doublit.c:782: error: ‘doublit’ undeclared (first use in this function) 
doublit.c:782: error: (Each undeclared identifier is reported only once 
doublit.c:782: error: for each function it appears in.) 
doublit.c:782: error: expected expression before ‘int’ 
doublit.c:793: error: expected expression before ‘double’ 
In file included from doublit.c:311: 
doublit.h:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘<’ token 
doublit.c: In function ‘initdoublit’: 
doublit.c:782: error: ‘doublit’ undeclared (first use in this function) 
doublit.c:782: error: (Each undeclared identifier is reported only once 
doublit.c:782: error: for each function it appears in.) 
doublit.c:782: error: expected expression before ‘int’ 
doublit.c:793: error: expected expression before ‘double’ 
lipo: can't figure out the architecture type of: /var/folders/ip/ip5rkteZFbWPEtzhmxRdVE+++Tc/-Tmp-//ccvaEGqZ.out 
error: command 'gcc-4.2' failed with exit status 1 
+1

Wyobrażam sobie, że potrzebujesz utworzyć instancję funkcji szablonu. –

+0

Wyobrażam sobie, że musisz podać C++ jako język dla cythonu do użycia podczas tłumaczenia. – jepio

Odpowiedz

4

Cython obsługuje składni szablonu, ale tylko dla klas (od Cython 0.19.1).

Chociaż można owinąć funkcje szablonów, używając następującej składni:

# doublit.pxd file 
cdef extern from "doublit.h": 
    cdef int doublit1 "doublit<int>"(int& foo) 
    cdef double doublit2 "doublit<double>"(double& foo) 

# main.pyx file 
from doublit cimport * 
cdef int n1 = 5 
cdef double n2 = 5.0 
print(doublit1(n1)) 
print(doublit2(n2)) 

Tracisz automatyzację, ale przynajmniej można dokonać.

UPDATE

Cython 0.20 dodaje wsparcie dla C++ wywoływania funkcji szablonu. Cython 0.20 beta release announced.

+0

Dzięki za pomoc. Ale mam kolejne trudności, gdy staram się podążać twoją drogą. –

+0

Czy możesz wrócić do mojego posta i rzucić okiem? Thx –

+0

@YunzhiMa Już odpowiedziałem na twoją odpowiedź, zobacz mój komentarz poniżej twojej odpowiedzi. –