从Python调用C ++ API时dynamic_cast失败

时间:2011-11-04 14:27:47

标签: c++ python

我试图从python调用C ++ API。以下是伪形式的代码。

class Engine { // Singleton Class which does a heavy duty work
public:
    static Engine* getEngine();
    bool init();
private:
    static Engine* m_instance;
    Engine();
};

// Following the code to wrap the call to engine to call from python
// Its only a simplified form

//engine_module.c
#include <Engine.h>
PyObject* initengine() {
    Engine* e = Engine::getInstance();
    e->init();
   // return the Py_BuildValue ...   
}

PyObject* initengine_module() {
//... init the module
}

// Python code
import engine_module
status = engine_module.init() 

问题: Engine类在libengine.so中,并且当它内部失败时,因为内部dynamic_cast失败。 Engine依次使用dlopen()加载其他库。我搜索网络时添加了RTDL_GLOBAL和-E选项,但链接仍未解决。我应该在编译python时添加-E选项吗? 当在C ++代码中使用Engine类时,它可以正常工作,并且在python中使用时不起作用的原因是什么?

编辑1: 澄清Cat ++的问题: libengine.so还有许多其他类,它们在Engine :: init()内部使用dynamic_cast&lt;&gt;。 dynamic_cast中涉及的类根本不会暴露给python。只暴露了Engine :: init()。

编辑2: 该平台是Red Hat Linux,编译器是Intel

2 个答案:

答案 0 :(得分:1)

问题是如何以及何时加载动态库。代码 你在engine_module.c中显示引用Engine,所以库有 在任何初始化之前,{em}将自动加载Engine 执行engine_module.c中的代码。同样,使用的任何库 在加载Engine的库之前,将加载Engine。所有 其中将使用Python用于加载它的标志加载 接口模块。 (RTDL_LOCAL是我的猜测。)你调用的任何dlopen 稍后会发现该模块已经被加载,并忽略了 请求 - 包括忽略您可能拥有的任何dlopen选项 过去了。

我们解决这个问题的方法是创建一个特殊的加载器模块 包含 no 对任何其他模块的直接引用。蟒蛇 加载此模块,该模块实现initxxx功能。该 initxxx函数显式加载所需的所有其他模块 依赖确定的顺序。 (如果A使用B,B将在A之前加载。) 当然是RTDL_GLOBAL。在你的情况下,这将是 Engine使用的库,然后是Engine。要加载的最后一个模块 将是具有Python接口的那个;我们把Python 初始化代码在静态对象的构造函数中,所以它会 在加载对象时自动执行,但您也可以 把它放在一个命名函数中,只要你得到它的地址 函数使用dlsym,而不是在其中声明extern 时尚。重要的是确保所有库首先由显式dlopen加载,而不是由于先前加载的某个库中未定义的外部而隐式地加载。

答案 1 :(得分:0)

我最好的猜测是,您正在尝试将dynamic_cast应用于某些非多态类,而这是失败的地方。请记住,dynamic_cast仅适用于具有至少一个虚方法(析构函数计数)的类。

相关问题