2013-08-01 58 views
7

我有許多在C++頭文件中聲明和實現的C++模板函數,我想訪問Cython中的一些函數。在Cython中調用外部C++模板函數

假設C++代碼是header.hpp如下

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

什麼我需要在.pyx文件和setup.py文件來寫,這樣我可以在Python中使用該功能

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

PS:是否可以在PYPY中訪問相同的函數?如果是,如何?


感謝您的幫助。但當我試圖按照自己的方式行事時,我遇到了更多的困難(下文)。

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)) 

和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 
) 

最後,我作爲構建

>>> python setup.py build_ext --inplace 

,但我得到以下異常:

###: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

我想你需要實例化模板函數。 –

+0

我會想象你需要指定C++作爲cython在翻譯時使用的語言。 – jepio

回答

4

用Cython支持模板語法,但僅適用於類(如用Cython 0.19.1的)。

雖然你可以使用下面的語法包裝的模板功能:

# 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)) 

你失去了自動化,但至少你可以把它的工作。

UPDATE

用Cython 0.20增加了對調用C++模板函數的支持。 Cython 0.20 beta release announced

+0

感謝您的幫助。但當我試圖按照自己的方式行事時,我遇到了更多的困難。 –

+0

你能回到我的文章並看看嗎? Thx –

+0

@YunzhiMa我已經回答了你的回答,請在你的回答下面看到我的評論。 –