我们有一个插件,它由我们的应用程序中的一些共享库构成,我们需要在应用程序运行时更新它们。出于性能原因,我们在卸载旧插件之前加载并开始使用新插件,并且只有当使用旧插件完成所有线程时,我们才会卸载它。由于新插件的库和旧插件中的符号相同,我们dlopen()
与RTLD_LOCAL
。如果我们没有新的插件从内部函数调用到旧插件的符号。
插件的一个库对由插件的另一个库创建的对象执行dynamic_cast()
。这适用于HP-UX,AIX,Solaris和Windows,但不适用于Linux。据我所知,这是因为所有这些操作系统(编译器)都使用类的名称来比较类型(在dynamic_cast()
中),但Linux使用名称字符串地址来进行此比较(以提高性能),因为每个库都有自己的type_info
对象(因为它加载了RTLD_LOCAL
)地址不同,因此相等的类型似乎不等于dynamic_cast()
。
有没有办法执行以下操作之一:
type_info
个对象,就像提供了RTLD_GLOBAL
一样。type_info
地址来比较类型。?我们使用的编译器是:
$ icpc -V
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.0.084 Build 20101006
Copyright (C) 1985-2010 Intel Corporation. All rights reserved.
答案 0 :(得分:4)
好的,我们最终做的是解决这个问题。
我们在类中添加了dynamic_cast()
两个静态函数:
static MyClass* doNew();
static MyClass* doDynCast(MyBase*);
这些是在cpp文件中实现的,它将new
,dynamic_cast()
和type_info
对象保存在同一个lib中,从而使dynamic_cast()
能够解决问题
这个解决方案足以满足我们的特定情况,但是如果有人有更通用的解决方案,那将会受到欢迎。
我们发现的另一个选项是将类的所有实现放在cpp文件中,这使得typeinfo
符号仅存在于一个库中,而所有其他库仅引用它。这导致成功dynamic_cast()
。
答案 1 :(得分:2)
不幸的是,因为type_info结构是创建它们的库本地的弱符号,所以不容易使dynamic_cast
工作。您可以尝试操作类vtable(和type_info)实例化的位置;在GCC上,可以通过确保仅在公共共享依赖库中定义the first non-inline function in the class (in order of definition)来完成此操作。如果您的类没有非内联函数,请创建一个虚拟函数以强制执行此生成。但请注意,我没有对此进行测试,因此无法保证它能够正常工作。另外,这是依赖于编译器的;我不知道英特尔的编译器做了什么。
当然,您可以使用类名来实现自己的备用动态转换机制;有许多库也可以这样做,例如Qt的qobject_cast。