I have a number of c++ template functions declared and implemented in a c++ header file and I want to access some of the functions within Cython.
Suppose the c++ code is in header.hpp
as follows
template <class T>
T doublit(T& x) {
return 2*x;
}
What do I need to write in the .pyx file and in the setup.py file so that I can use the function in Python as
>>> import modname
>>> print modname.doublit(3)
6
PS: Is it possible to access the same functions within PYPY? And, if yes, how?
Thanks for helping. But I have further difficulties (below) as I try to follow your way.
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))
and 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
)
Finally, I build as
>>> python setup.py build_ext --inplace
but I get the following exception:
###: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
Cython supports template syntax but only for classes (as of Cython 0.19.1).
Although you can wrap template functions using the following syntax:
# 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))
You lose the automation, but at least you can make it work.
UPDATE
Cython 0.20 adds support for calling C++ template functions. Cython 0.20 beta release announced.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With