2011-11-04 123 views
1

我试图从python调用C++ API。以下是伪造形式的代码。dynamic_cast在从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() 

问题: 引擎类是libengine.so,当它inits,因为内部的dynamic_cast失败,失败。引擎轮流使用dlopen()加载其他库。我在搜索网络时添加了RTDL_GLOBAL和-E选项,但仍未解决。我是否应该在编译python的时候添加-E选项? 在C++代码中使用Engine类时能够完美地工作,而在python中使用时不起作用的原因是什么?

编辑1: 为了阐明来自猫++这样的问题: libengine.so具有在内部引擎::的init()使用的dynamic_cast <>许多其他类。 dynamic_cast中涉及的类根本不暴露给python。只有Engine :: init()被公开。

编辑2: 该平台是Red Hat Linux和编译器是英特尔

+0

这段代码都没有'dynamic_cast'。另外,不要使用单身人士。 –

+1

libengine.so有很多其他的类,内部在Engine :: init()中使用dynamic_cast <>。 dynamic_cast中涉及的类根本不暴露给python。只有Engine :: init()被公开。 – Sudeep

+1

如果你用C++编写测试程序,并调用'Engine :: init',它会工作吗? –

回答

1

问题是如何以及何时加载动态库。您在engine_module.c显示代码 引用Engine,所以用 Engine图书馆将前被自动加载执行任何engine_module.c初始化 代码。同样, Engine所使用的任何库都将在加载Engine的库之前加载。所有的 都将使用Python用于加载其接口模块的标志进行加载。 (RTDL_LOCAL是我的猜测)。任何dlopen调用 后来会发现,该模块已经被加载,而忽视了 要求—包括忽略任何选项dlopen你可能有 通过。

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

+0

谢谢詹姆斯,我一定会尝试这个,并在这里发布结果。 – Sudeep

+0

我加载了libengine.so使用dlopen加载我的python模块的时刻,并且这个工作非常漂亮。没有必要为链接器添加-E标志。我将写一个小博客来逐步解释这个问题,并链接到这个页面。非常感谢詹姆斯。 – Sudeep

+0

@Sudeep我忘了提及我们没有使用'-E'选项。而据我所知,它只影响可执行文件的链接,而不影响共享库的链接。 –

0

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

+0

够公平的。但是,所讨论的基类具有虚拟功能。 – Sudeep