我们有一个插件,它由应用程序中的一些共享库构成,我们需要在应用程序运行时更新这些库。出于性能原因,我们在卸载旧插件之前加载并开始使用新插件,并且只有当所有线程都使用旧插件完成时,我们才卸载它。由于新插件和旧插件的库中有相同的符号,我们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.
Run Code Online (Sandbox Code Playgroud)
好的,我们最终做的是解决了这个问题。
我们向类中添加了我们想要的dynamic_cast()两个静态函数:
static MyClass* doNew();
static MyClass* doDynCast(MyBase*);
Run Code Online (Sandbox Code Playgroud)
这些是在 cpp 文件中实现的,该文件将new、dynamic_cast()和type_info对象保存在同一个库中,从而dynamic_cast()解决了问题。
这个解决方案对于我们的具体情况已经足够了,但如果有人有更通用的解决方案,它将受到欢迎。
我们发现的另一种选择是将类的所有实现放在 cpp 文件中,这使得typeinfo符号仅存在于一个库中,而所有其他库仅引用它。这导致成功的dynamic_cast().