Dynamic_cast 来自由 lt_dlopen(libtool) 加载的共享库的接口不起作用
这是关于我的程序中的插件功能。我需要插件中的 C++ 类(和对象)可以由主模块通过接口使用。 接口继承是这样的:
typedef struct _rwd_plugin_root_t RWD_PLUGIN_ROOT_T;
struct RWD_PLUGIN_API _rwd_plugin_root_t
{
virtual int add_ref() = 0;
virtual int release() = 0;
};
typedef struct _rwd_plugin_base_t RWD_PLUGIN_BASE_T;
struct RWD_PLUGIN_API _rwd_plugin_base_t : _rwd_plugin_root_t
{
virtual RWD_PLUGIN_TYPE_T get_plugin_type() = 0;
virtual const char * get_plugin_label_a() = 0;
virtual const wchar_t * get_plugin_label_w() = 0;
};
typedef struct _rwd_autocomplete_plugin_base_t RWD_AUTOCOMPLETE_PLUGIN_BASE_T;
struct RWD_PLUGIN_API _rwd_autocomplete_plugin_base_t : _rwd_plugin_base_t
{
virtual int set_proxy(int type, const char * host, long port) = 0;
virtual int set_term(const char * text) = 0;
virtual int set_term(const wchar_t * text) = 0;
virtual int get_phon(std::vector<std::string> & phons) = 0;
... // omitted it's too long
};
然后我在插件中有一个类来实现这样的接口:
class RWD_PLUGIN_API _rwd_dictcn_t : public _rwd_autocomplete_plugin_base_t
{
public:
_rwd_dictcn_t();
~_rwd_dictcn_t();
... // details of implementation omitted
插件中的创建者定义如下:
EXTERN_C int RWD_PLUGIN_API create_rwd_plugin(_rwd_plugin_base_t ** pp)
{
*pp = new _rwd_dictcn_t();
return OK;
}
最后,我在主应用程序中使用创建者,以便像这样使用插件:
...
lt_dlhandle lh = lt_dlopen(filePath);
RWD_PLUGIN_CREATE_FUNC_T pPluginFunc = NULL;
if(lh)
{
pPluginFunc = reinterpret_cast<RWD_PLUGIN_CREATE_FUNC_T>(lt_dlsym(lh, "create_rwd_plugin"));
if(pPluginFunc)
{
RWD_PLUGIN_BASE_T * pBase = NULL;
if(OK == (*pPluginFunc)(&pBase))
{
RWD_PLUGIN_TYPE_T pluginType = pBase->get_plugin_type();
if(pluginType == RWD_PLUGIN_TYPE_AUTOCOMPELE)
{
...
RWD_PLUGIN_FUNC_T pPluginInitFunc = reinterpret_cast<RWD_PLUGIN_FUNC_T>(lt_dlsym(lh, "initialize_rwd_plugin"));
if(pPluginInitFunc)
(*pPluginInitFunc)(NULL);
// set proxy
RWD_AUTOCOMPLETE_PLUGIN_BASE_T * pAuto = dynamic_cast<RWD_AUTOCOMPLETE_PLUGIN_BASE_T*>(pBase);
...
问题Dynamic_cast 总是失败并且 pAuto 最终为零。 不过WIN32版本工作正常。 该问题发生在带有 autoconf2.61 automake1.10.1 make3.81 g++4.4.4 libtool1.5.26 的 Linux 上。 我对 Linux 编程的经验较少,希望在这里得到帮助。谢谢!
如有必要,可以在 Sourceforge 上获取完整的源代码: svn co <a href="https://rdwtwdb.svn.sourceforge.net/svnroot/rdwtwdb" rel="nofollow noreferrer">https://rdwtwdb.svn.sourceforge.net/svnroot/rdwtwdb rdwtwdb
This is about plugin features in my program. I need a C++ class(and object) in a plugin could be used by main module through an interface.
The interface inheritance like this:
typedef struct _rwd_plugin_root_t RWD_PLUGIN_ROOT_T;
struct RWD_PLUGIN_API _rwd_plugin_root_t
{
virtual int add_ref() = 0;
virtual int release() = 0;
};
typedef struct _rwd_plugin_base_t RWD_PLUGIN_BASE_T;
struct RWD_PLUGIN_API _rwd_plugin_base_t : _rwd_plugin_root_t
{
virtual RWD_PLUGIN_TYPE_T get_plugin_type() = 0;
virtual const char * get_plugin_label_a() = 0;
virtual const wchar_t * get_plugin_label_w() = 0;
};
typedef struct _rwd_autocomplete_plugin_base_t RWD_AUTOCOMPLETE_PLUGIN_BASE_T;
struct RWD_PLUGIN_API _rwd_autocomplete_plugin_base_t : _rwd_plugin_base_t
{
virtual int set_proxy(int type, const char * host, long port) = 0;
virtual int set_term(const char * text) = 0;
virtual int set_term(const wchar_t * text) = 0;
virtual int get_phon(std::vector<std::string> & phons) = 0;
... // omitted it's too long
};
Then I have a class in plugin to implement the interface like this:
class RWD_PLUGIN_API _rwd_dictcn_t : public _rwd_autocomplete_plugin_base_t
{
public:
_rwd_dictcn_t();
~_rwd_dictcn_t();
... // details of implementation omitted
The creator in plugin is defined like this:
EXTERN_C int RWD_PLUGIN_API create_rwd_plugin(_rwd_plugin_base_t ** pp)
{
*pp = new _rwd_dictcn_t();
return OK;
}
At last, I use the creator in main application so as to use the plugin like this:
...
lt_dlhandle lh = lt_dlopen(filePath);
RWD_PLUGIN_CREATE_FUNC_T pPluginFunc = NULL;
if(lh)
{
pPluginFunc = reinterpret_cast<RWD_PLUGIN_CREATE_FUNC_T>(lt_dlsym(lh, "create_rwd_plugin"));
if(pPluginFunc)
{
RWD_PLUGIN_BASE_T * pBase = NULL;
if(OK == (*pPluginFunc)(&pBase))
{
RWD_PLUGIN_TYPE_T pluginType = pBase->get_plugin_type();
if(pluginType == RWD_PLUGIN_TYPE_AUTOCOMPELE)
{
...
RWD_PLUGIN_FUNC_T pPluginInitFunc = reinterpret_cast<RWD_PLUGIN_FUNC_T>(lt_dlsym(lh, "initialize_rwd_plugin"));
if(pPluginInitFunc)
(*pPluginInitFunc)(NULL);
// set proxy
RWD_AUTOCOMPLETE_PLUGIN_BASE_T * pAuto = dynamic_cast<RWD_AUTOCOMPLETE_PLUGIN_BASE_T*>(pBase);
...
The problem is dynamic_cast always fails and pAuto end up being a nil.
However the WIN32 version works fine.
The problem happened on linux with autoconf2.61 automake1.10.1 make3.81 g++4.4.4 libtool1.5.26 .
I have less experience with linux programming and hope getting help here. Thanks!
The full source code could be get on Sourceforge if necessary:
svn co https://rdwtwdb.svn.sourceforge.net/svnroot/rdwtwdb rdwtwdb
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试使用
-Wl,--export-dynamic
链接器参数进行构建。我记得遇到类似行为时需要这个论点。you might try building with
-Wl,--export-dynamic
linker argument. I recall needing this argument when encountering similar behavior.你的问题可能是私有继承:
_rwd_autocomplete_plugin_base_t : _rwd_plugin_base_t
另外,我认为因为你有虚拟函数,你的类型已经是多态的,但添加虚拟析构函数不会有什么坏处。
编辑:抱歉,刚刚意识到您在那里使用
struct
,因此默认继承是公共的。但可能最好是明确的,特别是因为您看到了编译器之间的差异。You're problem may be the private inheritance:
_rwd_autocomplete_plugin_base_t : _rwd_plugin_base_t
Also I think because you have virtual functions your types are already polymorphic, but wouldn't hurt to add virtual destructors.
Edit: Sorry just realized you're using
struct
there so the default inheritance is public. But probably best to be explicit, especially since you're seeing differences between compilers.