简体   繁体   English

在cygwin中为boost_python链接c ++ - 类

[英]Linking c++-class for boost_python in cygwin

I have been using a wrapper for a c++-class for exporting functions to python for a while on linux. 我一直在使用一个c ++包装器,用于在linux上将函数导出到python一段时间。 Now I wanted to make this available to my coworkers using windows. 现在我想让我的同事使用Windows。 However, I fail to create a usable boost_python dll for this in cygwin. 但是,我无法在cygwin中为此创建一个可用的boost_python dll。 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. 当我尝试将依赖模块链接到另一个dll时,如果我将依赖源编译到它按预期工作的相同dll中,则会出现问题。

I have a created a minimal example displaying the problem: 我创建了一个显示问题的最小示例:

The setup: 设置:

moduleB/moduleB.cpp # The boost wrapper code moduleB / moduleB.cpp#boost包装器代码

#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 submodule / submodule.hpp#包含c ++类的子模块

#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 submodule / submodule.cpp #c ++类定义
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). 然后我们编译实际的包装器代码并将其链接到我们应该能够从python导入的boost_python dll(验证包含的示例在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 . 在ubuntu中,在从.so文件中删除cyg -prefix并确保submodule.so位于LD_LIBRARY_PATH之后,可以按原样使用此模块。 However, cygwin shows the classic import error: 但是,cygwin显示了经典的导入错误:

>>> 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 . 检查的差异ldd上Cygwin和Ubuntu的一个之间的工作moduleB可以看出,升压和Python的DLL已经从输出beeen取代问号moduleB.dll

moduleB on cygwin: cygwin上的moduleB:

# 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: Ubuntu上的moduleB:

# 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? 想知道为什么moduleB无法将自己标识为cygwin中的boost_module,以及为什么g++无法包含适当的依赖信息?

boost_python was installed using the package in cygwin. 使用cygwin中的软件包安装了boost_python。


UPDATE : In addition to the correct answer below, two things should be noted that obfuscated the correct solution: 更新 :除了下面的正确答案之外,还应该注意两件事,这些问题模糊了正确的解决方案:

  1. ldd on cygwin does not give the same output as on ubuntu and instead of <library>.dll => not found it only displays something like ? => ? (<address>) 在cygwin上的ldd没有提供与ubuntu相同的输出,而不是<library>.dll => not found它只显示类似的东西? => ? (<address>) ? => ? (<address>)
  2. When loading a boost module in python on cygwin that depends on a dll not in path we do not get a message that a dll is missing, only that the boost module can not be found. 当加载一个boost在Cygwin上的Python模块依赖于dll没有路径,我们没有得到一个DLL文件丢失的消息,只有增强模块无法找到。

The following changes must be made: 必须进行以下更改:

  1. Link C++ programs and libraries with g++ . 使用g++链接C ++程序和库。
  2. Python module name must match file name, so if a file is named moduleB.dll there should be a line that says BOOST_PYTHON_MODULE(moduleB) in there somewhere. Python模块名称必须与文件名匹配,因此如果文件名为moduleB.dll那么应该有一行在某处显示BOOST_PYTHON_MODULE(moduleB)
  3. In order to actually load the module, it should be in the Python's sys.path , and all its dependencies should be in the windows %PATH% (or in the current directory, or wherever Windows allows to put dependent DLLs). 为了实际加载模块,它应该在Python的sys.path ,并且它的所有依赖项应该在windows %PATH% (或者在当前目录中,或者Windows允许放置依赖DLL的地方)。 LD_LIBRARY_PATH doesn't work in Cygwin the way it works in real Unix systems. LD_LIBRARY_PATH在Cygwin中不能像在真正的Unix系统中那样工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM