在动态库未定义引用中提升 python 包装器

Posted

技术标签:

【中文标题】在动态库未定义引用中提升 python 包装器【英文标题】:boost python wrapper in dynamic library undefined reference 【发布时间】:2012-11-18 21:38:09 【问题描述】:

我目前正在尝试将复杂程序的一部分放入动态库中。这部分由一些类组成,这些类也用 boost python 包装到一个模块中,以便再次嵌入。这是 dll 源的简化版本。

你好.cpp:

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <Foo.h>

using namespace boost::python;

typedef boost::shared_ptr<Hello> hello_ptr;

BOOST_PYTHON_MODULE(Hello)

    class_<Hello, hello_ptr>("Hello")
        .def("say_hello", &Hello::say_hello)
    ;
;


void Hello::say_hello()
    cout << "Hello World!" << endl;


void World::foo()
    Py_Initialize();

    try 
        PyRun_SimpleString(
            "hello = None\n"
            "\n"
            "def setup(hello_from_cxx):\n"
            "    print 'setup called with', hello_from_cxx\n"
            "    global hello\n"
            "    hello = a_foo_from_cxx\n"
            "\n"
            "def run():\n"
            "    hello.say_hello()\n"
            "\n"
            "print 'main module loaded'\n"
        );
        //initialize eviroment
        initHello();

        hello_ptr hello = boost::make_shared<Hello>();

        object main = object(handle<>(borrowed(
            PyImport_AddModule("__main__")
        )));

        // pass the reference to hello into python:
        object setup_func = main.attr("setup");
        setup_func(hello);

        // now run the python 'main' function
        object run_func = main.attr("run");
        run_func();
    
    catch (error_already_set) 
        PyErr_Print();
    

你好.h

#ifndef HELLO_H_INCLUDED
#define HELLO_H_INCLUDED

#include <iostream>
#include <boost/python.hpp>

using namespace std;

class Hello
public:
    void say_hello();
;

class World
public:
    void foo();
;

#endif // HELLO_H_INCLUDED

然后,在应用程序的主函数中,我创建了一个嵌入 python 的类的实例,但它给出了对 World::foo() 的未定义引用,即使该函数是在动态库 libFoo.dll 中定义的,它也是由主应用程序链接。

main.cpp:

#include <iostream>
#include <Hello.h>

using namespace std;

int main()
    cout << "Test" << endl;

    World world;

    world.foo();

控制台:

undefined reference to `World::foo()'

我在 MinGW 中使用 Code::Blocks。

这个问题让我有好几天没睡了,我似乎找不到解决它的方法。希望您能够帮助我。

提前致谢。

更新:

我现在尝试使用普通的 Python C API 来完成这项任务。定义与此错误肯定相关的 Python_Module (BOOST_PYTHON_MODULE()) 的步骤是通过定义如下函数来完成的:

PyMODINIT_FUNC initHello(void)
...

现在写在前面

#define PyMODINIT_FUNC void

解决了错误。现在有人知道 boost.python 库是如何定义 BOOST_PYTHON_MODULE 函数的吗?也许也有这种解决方案?我在源文件中找不到任何 PyMODINIT_FUNC 内容。

【问题讨论】:

【参考方案1】:

自己找到了解决方案。

好像我已经猜到了。需要的是像这样定义 BOOST_PYTHON_MODULE_INIT(name)。

#   define BOOST_PYTHON_MODULE_INIT(name)                               \
  void BOOST_PP_CAT(init_module_,name)();                               \
extern "C" __attribute__ ((__visibility__("default"))) _BOOST_PYTHON_MODULE_INIT(name)

实际上,我在其中一个带有#ifdef infront 的头文件中发现了这一点,但它们似乎无法正常工作。至少对我来说不是。

【讨论】:

以上是关于在动态库未定义引用中提升 python 包装器的主要内容,如果未能解决你的问题,请参考以下文章

TA-lib 库未安装在 pydroid 3 中?

[xamarin][uwp][custom renderer] 自定义渲染器 pcl 库未在发布模式下加载

CocoaLibSpotify - 库未加载

在 Python 中,如何定义一个函数包装器来验证具有特定名称的参数?

SWIG C++ Python:通过引用或指针包装 int

修改 Boost Python 包装类?