I have been using a wrapper for a c++-class for exporting functions to python for a while on linux. Now I wanted to make this available to my coworkers using windows. However, I fail to create a usable boost_python dll for this in cygwin. The problem arises when trying to link a dependent module in another dll, if I instead compile the dependent source into the same dll it works as expected.
I have a created a minimal example displaying the problem:
The setup:
moduleB/moduleB.cpp # The boost wrapper code
#include <python2.7/Python.h> #include <boost/python.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp> #include "submodule.hpp" using namespace boost::python; using namespace testspace; using namespace std; struct cModuleB : public SubModuleClass { cModuleB(string name, bool boolVar) : SubModuleClass(name, boolVar) { } void printFunc(string strVar, list listVar, int nIntVar=-1) { vector<int> vecList; for (int l=0; l < len(listVar); l++) { vecList.push_back(extract<int>(listVar[l])); } bool bMoreThanHalf = subModuleFunction(vecList); if (bMoreThanHalf) { cout << "More than half elements are more than 1"; } return; } }; BOOST_PYTHON_MODULE(moduleB) { class_<cModuleB>("cModuleB", init<std::string, bool>()) .def("printFunc", &cModuleB::printFunc); }
submodule/submodule.hpp # The submodule containing the c++ class
#include <vector> #include <string> using namespace std; namespace testspace { class SubModuleClass { public: SubModuleClass(string name = "", bool bIsGreat = false); ~SubModuleClass(); bool subModuleFunction(vector<int> & myVec); }; }
- submodule/submodule.cpp # The c++ class definition
using namespace std; #include "submodule.hpp" using namespace testspace; SubModuleClass::SubModuleClass(string name, bool bIsGreat) { } SubModuleClass::~SubModuleClass() { } bool SubModuleClass::subModuleFunction(vector<int> & myVec) { int nCounter = 0; for (vector<int>::iterator vi = myVec.begin(); vi != myVec.end(); vi++) { if (*vi > 1) nCounter++; } if (nCounter*2 > (int)myVec.size()) { return true; } else { return false; } }
First we compile submodule into a shared library by the following two commands:
g++ -MMD -MP -ffloat-store -m64 -O0 -ggdb -DDEBUG -D_DEBUG \ -c submodule/submodule.cpp -o submodule/submodule.o g++ -m64 -shared -Wl,-soname=cygsubmodule_for_moduleB.dll \ -Wl,--whole-archive submodule/submodule.o -Wl,--no-whole-archive \ -Wl,--out-implib,./libsubmodule_for_moduleB.dll.a \ -Wl,--export-all-symbols -Wl,--enable-auto-import \ -o submodule/cygsubmodule.dll
And the we compile the actual wrapper code and link it into a boost_python dll that we should be able to import from python (verified that the included example works find on ubuntu).
g++ -MMD -MP -ffloat-store -m64 -O0 -ggdb -fPIC \ -Isubmodule -I/usr/include/python2.7 -DDEBUG -D_DEBUG \ -c moduleB/moduleB.cpp -o moduleB/moduleB.o g++ -m64 -shared -Wl,-soname=cygmoduleB.dll \ -Wl,--whole-archive moduleB/moduleB.o -Wl,--no-whole-archive \ -Wl,--out-implib,./libmoduleB.dll.a -Wl,--export-all-symbols \ -Wl,--enable-auto-import -Lsubmodule -lsubmodule -lstdc++ -lboost_python -lpython2.7 -o moduleB/cygmoduleB.dll
In ubuntu this module can be used as is after removing the cyg
-prefix from the .so
file and making sure that the submodule.so
is in the LD_LIBRARY_PATH
. However, cygwin shows the classic import error:
>>> import moduleB Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No such file or directory
Examining the differences of ldd
on the working moduleB between cygwin and Ubuntu one can see that the boost and python dlls have beeen replaced by question marks in the output from moduleB.dll
.
moduleB on cygwin:
# ldd moduleB.dll ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x778b0000) kernel32.dll => /cygdrive/c/Windows/system32/kernel32.dll (0x77470000) KERNELBASE.dll => /cygdrive/c/Windows/system32/KERNELBASE.dll (0x7fefdfd0000) SYSFER.DLL => /cygdrive/c/Windows/System32/SYSFER.DLL (0x75090000) ??? => ??? (0x4f3d00000)
moduleB on Ubuntu:
# ldd moduleB.so linux-vdso.so.1 => (0x00007fff55b73000) libsubmodule.so => libsubmodule.so (0x00007fee4f9d7000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fee4f6a8000) libpython2.7.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0 (0x00007fee4f144000) libboost_python-py27.so.1.55.0 => /usr/lib/x86_64-linux-gnu/libboost_python-py27.so.1.55.0 (0x00007fee4eef7000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fee4ece1000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fee4e91b000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fee4ddbf000) /lib64/ld-linux-x86-64.so.2 (0x000055f47c1a6000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fee4dba0000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fee4d987000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fee4d783000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fee4d580000)
Any idea as to why moduleB fails to identify itself as a boost_module in cygwin, and why g++
fails to include the appropriate dependency information?
If I instead compile the submodule.cpp
together with the moduleB.cpp
and remove the dependency on the separate submodule.dll
then everything works as expected.
boost_python was installed using the package in cygwin.
EDIT: Apart from my system (in which I have tried both cygwin64 and cygwin32), a Windows7 64-bit installed in VirtualBox in Ubuntu 14.04, two of my coworkers with native Windows 7 64-bit have tried the above installment getting the same results as me with the question marks from ldd
. Very strange that @n.m. got this working but none of us. Still I have no clue as to what the question marks signify. If anybody can shed some light on that I would also be grateful.
0 comments:
Post a Comment