2017-01-30 1 views
9

저는 리눅스에서 파이썬으로 함수를 내보내는 C++ 클래스의 래퍼를 사용하고 있습니다. 이제 창을 사용하여 동료들도이 기능을 사용할 수있게하려고했습니다. 그러나, 나는 cygwin에서 이것을 위해 쓸만한 boost_python dll을 만들지 못한다. 문제는 다른 DLL에서 종속 모듈을 링크하려고 할 때 발생합니다. 대신 종속 소스를 예상대로 작동하는 동일한 DLL로 컴파일하면 문제가 발생합니다.cygwin에서 boost_python을위한 C++ - 클래스를 연결합니다.

셋업 :

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; 
    } 
} 

전나무

나는이 문제를 표시하는 최소한의 예를 만들었습니다 일 우리는 다음과 같은 두 가지 명령에 의해 공유 라이브러리에 서브 모듈을 컴파일 :

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 

그리고 우리가 실제 래퍼 코드를 컴파일하고 우리는 파이썬에서 가져올 수해야 boost_python의 DLL로 링크 (포함 된 것을 확인 예제는 우분투에서 찾을 수 있습니다).

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 

우분투에서이 모듈은 .so 파일에서 cyg -prefix를 제거하고 submodule.soLD_LIBRARY_PATH에 있는지 확인 한 후 그대로 사용할 수 있습니다.

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

부스트와 비단뱀의 DLL이 moduleB.dll의 출력에 물음표로 대체를 켜고 수분 것을 볼 수 있습니다 Cygwin에서 우분투 하나의 작업 moduleB에 ldd의 차이를 검사 : 그러나, 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 :

# 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++ 적절한를 포함하는 데 실패하는 이유 의존성 정보?

boost_python이 cygwin에서 패키지를 사용하여 설치되었습니다.시그윈에

  1. lddubuntu에 동일한 출력을 제공하지 않으며, 아래 두 가지가 정확한 솔루션을 난독 주목해야한다 정답 외에 :


    UPDATE에게<library>.dll => not found 대신 ? => ? (<address>)

  2. boost 모듈을 01에 의존하는 cygwin의 python으로로드 할 때경로에 없으면 dll이 없다는 메시지가 나타나지 않고 부스트 모듈을 찾을 수 없습니다.
+0

g ++, 마침표로 링크 된 C++ 모듈. gcc 또는 다른 어떤 것이 작동해야한다고 누가 말했습니까? 어쨌든 make가 호출 한대로 실제 빌드 명령을 표시하십시오. –

+0

@ n.m. 게시물을 완전한 작동 예제로 업데이트했습니다. – fnokke

+0

모듈 이름과 파일 이름이 일치하지 않습니다. cyfmoduleB.dll을 빌드하지만 moduleB.dll이라고해야합니다. CygmoduleB.dll을 moduleB.dll로 이름을 바꾼 단계를 재현했으며 결과는 Python과 완벽하게 잘 작동하는 모듈입니다 (gcc 5.4.0, 오늘 업데이트 된 cygwin). –

답변

1

다음 사항을 변경해야합니다 :

  1. 링크 C++ 프로그램과 라이브러리를 g++로.
  2. 파이썬 모듈 이름은 파일 이름과 일치해야합니다. 따라서 파일의 이름이 moduleB.dll 인 경우 어딘가에 BOOST_PYTHON_MODULE(moduleB)이라는 줄이 있어야합니다.
  3. 실제로 모듈을로드하려면 모듈은 sys.path이어야하고 모든 종속성은 %PATH% (또는 현재 디렉토리 또는 Windows가 종속 DLL을 둘 수있는 곳)에 있어야합니다. LD_LIBRARY_PATH은 실제 Unix 시스템에서 작동하는 방식으로 Cygwin에서 작동하지 않습니다.
관련 문제