在cygwin中链接boost_python的c++类
Linking c++-class for boost_python in cygwin
我在linux上使用c++类的包装器将函数导出到python已经有一段时间了。现在我想让我的同事使用windows来使用它。然而,我未能在cygwin中为此创建一个可用的boost_python dll。当试图链接另一个dll中的依赖模块时会出现问题,如果我将依赖源编译到同一个dll,它会按预期工作。
我创建了一个显示问题的最小示例:
设置:
moduleB/moduleB.cpp#升压包装代码
#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.hp#包含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
我们编译了实际的包装器代码,并将其链接到一个boost_python dll中,我们应该能够从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
-前缀并确保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
通过检查cygwin和Ubuntu在工作模块B上的ldd
的差异,可以看到在moduleB.dll
的输出中,boost和python-dll已经被问号取代。
cygwin上的模块B:
# 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)
关于为什么模块B未能在cygwin中将自己标识为boost_module,以及为什么g++
未能包含适当的依赖性信息,有什么想法吗?
boost_python是使用cygwin中的包安装的。
更新:除了下面的正确答案外,还有两件事需要注意,它们混淆了正确的解决方案:
- cygwin上的
ldd
不会给出与ubuntu
相同的输出,而不是<library>.dll => not found
,它只显示类似? => ? (<address>)
的内容 - 当在cygwin上的python中加载依赖于不在路径中的
dll
的boost
模块时,我们不会得到缺少dll的消息,只是找不到boost模块
必须进行以下更改:
- 用
g++
链接C++程序和库 - Python模块名称必须与文件名相匹配,所以如果文件名为
moduleB.dll
,那么应该有一行在某处显示BOOST_PYTHON_MODULE(moduleB)
- 为了实际加载模块,它应该在Python的
sys.path
中,并且它的所有依赖项都应该在windows的%PATH%
中(或者在当前目录中,或者在windows允许放置依赖DLL的任何位置)。LD_LIBRARY_PATH
在Cygwin中的工作方式与在真实Unix系统中的工作方法不同
相关文章:
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- Pybind11:将元组列表从Python传递到C++
- 如何在c++中使用引用实现类似python的行为
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 递归列出所有目录中的C++与Python与Ruby的性能
- IPC使用多个管道和分支进程来运行Python程序
- 从python中调用C++函数并获取返回值
- Python 3.7 和 excess_args 的 SWIG 问题
- Python中的for循环与C++有何不同
- 使用Pybind11向Python公开Eigen::张量
- Python str to C++ to Python str
- 如何使用Python从C++中读取谷物序列化数据
- 如何在C++中使用pybind11加载一个pickle python列表
- 如何在c++中使用system()来运行包含空格的python脚本
- python集合的C++等价物是什么.计数器
- 如果C++对象的类在另一个boost模块中声明,如何使用boost将指向该对象的指针返回到python
- 从python调用openMP共享库时,未定义opnMP函数
- 使用JsonCpp将数据返回到带有pybind11的python会在python调用中产生Symbol not foun
- 如何将真正的字符串从python c-api转换为python脚本
- Python ctype 'c_char_p' Memory Leak