4

我们有一个插件,它由应用程序中的一些共享库构成,我们需要在应用程序运行时对其进行更新。出于性能原因,我们在卸载旧插件之前加载并开始使用新插件,并且只有当所有线程都使用旧插件完成时,我们才会卸载它。由于新插件和旧插件的库具有相同的符号,因此我们dlopen()使用RTLD_LOCAL. 如果我们不意外地将新插件从内部函数调用到旧插件中的符号。

插件的一个库对由插件dynamic_cast()的另一个库创建的对象执行。这适用于 HP-UX、AIX、Solaris 和 Windows,但不适用于 Linux。据我所知,这是因为所有这些操作系统(编译器)都使用类的名称来比较类型(在dynamic_cast().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.
4

2 回答 2

5

好的,我们最终所做的是解决了这个问题。

我们向类中添加了我们想要的dynamic_cast()两个静态函数:

static MyClass* doNew();
static MyClass* doDynCast(MyBase*);

这些是在 cpp 文件中实现的,该文件将new、 thedynamic_cast()type_infoobject 保存在同一个库中,从而dynamic_cast()解决了这个问题。

这个解决方案对于我们的具体情况已经足够了,但是如果有人有更通用的解决方案,它将受到欢迎。

我们发现的另一种选择是将类的所有实现放在 cpp 文件中,这使得typeinfo符号仅存在于一个库中,而所有其他库仅引用它。这导致一个成功的dynamic_cast().

于 2011-05-24T13:53:07.517 回答
3

不幸的是,因为 type_info 结构对于创建它们的库来说是本地的弱符号,所以不容易dynamic_cast工作。但是,您可以尝试操作类 vtable(和 type_info)的实例化位置;在 GCC 上,这可以通过确保类中的第一个非内联函数(按定义顺序)仅在公共共享依赖库中定义来完成。如果您的类没有非内联函数,请创建一个虚拟函数以强制这一代发生。但是请注意,我没有对此进行测试,因此不能保证它会起作用。此外,这取决于编译器;我不知道英特尔的编译器是做什么的。

当然,您可以使用类名来实现您自己的替代动态转换机制;有许多库也可以做到这一点,例如 Qt 的qobject_cast

于 2011-05-24T20:12:46.703 回答