簡體   English   中英

在cygwin中為boost_python鏈接c ++ - 類

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

我一直在使用一個c ++包裝器,用於在linux上將函數導出到python一段時間。 現在我想讓我的同事使用Windows。 但是,我無法在cygwin中為此創建一個可用的boost_python dll。 當我嘗試將依賴模塊鏈接到另一個dll時,如果我將依賴源編譯到它按預期工作的相同dll中,則會出現問題。

我創建了一個顯示問題的最小示例:

設置:

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#包含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 #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;
    }
}

首先,我們通過以下兩個命令將子模塊編譯為共享庫:

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

然后我們編譯實際的包裝器代碼並將其鏈接到我們應該能夠從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

在ubuntu中,在從.so文件中刪除cyg -prefix並確保submodule.so位於LD_LIBRARY_PATH之后,可以按原樣使用此模塊。 但是,cygwin顯示了經典的導入錯誤:

>>> import moduleB
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No such file or directory

檢查的差異ldd上Cygwin和Ubuntu的一個之間的工作moduleB可以看出,升壓和Python的DLL已經從輸出beeen取代問號moduleB.dll

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)

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)

想知道為什么moduleB無法將自己標識為cygwin中的boost_module,以及為什么g++無法包含適當的依賴信息?

使用cygwin中的軟件包安裝了boost_python。


更新 :除了下面的正確答案之外,還應該注意兩件事,這些問題模糊了正確的解決方案:

  1. 在cygwin上的ldd沒有提供與ubuntu相同的輸出,而不是<library>.dll => not found它只顯示類似的東西? => ? (<address>) ? => ? (<address>)
  2. 當加載一個boost在Cygwin上的Python模塊依賴於dll沒有路徑,我們沒有得到一個DLL文件丟失的消息,只有增強模塊無法找到。

必須進行以下更改:

  1. 使用g++鏈接C ++程序和庫。
  2. Python模塊名稱必須與文件名匹配,因此如果文件名為moduleB.dll那么應該有一行在某處顯示BOOST_PYTHON_MODULE(moduleB)
  3. 為了實際加載模塊,它應該在Python的sys.path ,並且它的所有依賴項應該在windows %PATH% (或者在當前目錄中,或者Windows允許放置依賴DLL的地方)。 LD_LIBRARY_PATH在Cygwin中不能像在真正的Unix系統中那樣工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM