草庐IT

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

coder 2023-08-19 原文

一段时间以来,我一直在使用 C++ 类的包装器将函数导出到 Python。现在我想使用 Windows 将其提供给我的同事。但是,我无法在 cygwin 中为此创建可用的 boost_python dll。尝试链接另一个 dll 中的依赖模块时会出现问题,如果我改为将依赖源编译到同一个 dll 中,它会按预期工作。

我创建了一个显示问题的最小示例:

设置:

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

然后我们编译实际的包装器代码并将其链接到我们应该能够从 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 中,这个模块可以在删除 cyg 后按原样使用。 - 来自 .so 的前缀文件并确保 submodule.soLD_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 之间的工作模块 B 上,可以看到在 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 上的模块 B:

# 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. ldd在 cygwin 上不提供与在 ubuntu 上相同的输出而不是 <library>.dll => not found它只显示类似 ? => ? (<address>) 的内容
  2. 加载 boost 时cygwin 上的 python 模块依赖于 dll不在路径中,我们没有收到 dll 丢失的消息,只是找不到 boost 模块。

最佳答案

必须进行以下更改:

  1. 将 C++ 程序和库与 g++ 链接起来。
  2. Python 模块名称必须与文件名匹配,因此如果文件名为 moduleB.dll,则在某处应该有一行内容为 BOOST_PYTHON_MODULE(moduleB)
  3. 为了实际加载模块,它应该在 Python 的 sys.path 中,并且它的所有依赖项应该在 windows %PATH% 中(或在当前目录,或 Windows 允许放置相关 DLL 的任何位置)。 LD_LIBRARY_PATH 在 Cygwin 中的工作方式与在真实 Unix 系统中的工作方式不同。

关于python - 在 cygwin 中为 boost_python 链接 c++ 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41941152/

有关python - 在 cygwin 中为 boost_python 链接 c++ 类的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  4. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  5. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  6. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  7. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  8. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

随机推荐