I compiled the C++ rnnlib as shared library and want to call it from python. I chose cython and created a a c++ function
void libCall(int argc, char* argv[])
(which is actually the same as the main function of rnnlib but renamed it to make it easier callable). The rnnlib library is inside /usr/lib
rnn.pyx
# distutils: language = c++
cdef extern from "libcall.hpp":
void libCall(int argc, char* argv[])
cpdef call():
print 'hallo welt'
setuprnn.py
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
import os
os.environ["CC"] = "gcc"
os.environ["CXX"] = "g++"
os.environ["CFLAGS"]="-I./src/"
setup(ext_modules = cythonize(
"rnn.pyx",
libraries=["rnnlib","netcdf_c++","netcdf","m","stdc++"],
language="c++",
))
Additional test.cpp
#include <iostream>
#include "libcall.hpp"
using namespace std;
int main(int argc, char* argv[]) {
libCall(argc, argv);
}
Building test.cpp with
g++ -Wall -I./src/ test.cpp -lrnnlib -lnetcdf_c++ -lnetcdf -lm -lstdc++ -o test
works.
When I run python setuprnn.py build_ext -i
I get rnn.so
and rnn.cpp
. But when trying to import rnn
in Python:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: ./rnn.so: undefined symbol: _ZNK5NcVar3getEPcPKl
Inspecting rnn.so
with nm yields:
000000000003f140 W _ZNK5Mdrnn5printERSo
U _ZNK5NcDim4sizeEv
U _ZNK5NcVar3getEPcPKl
This is strange, because this is the missing symbol.
The problem are the dependencies of my libraries. Cython does not handle them.
The python script from above (setuprnn.py) does nothing else but execute this:
cython ...
gcc ...
g++ ... -lrnnlib -lnetcdf -lstdc++ -o rnn.so
This creates a problem as stated above in the entry post. The solution is then just to create a shell script for creating the library:
#!/bin/sh
cython ...
gcc ...
g++ ... -o rnn.so -lnetcdf_c++ -lnetcdf -lm -lstdc++ -lrnnlib