C++ Linux上的RTLD_本地和动态_转换

C++ Linux上的RTLD_本地和动态_转换,c++,linux,dlopen,C++,Linux,Dlopen,我们有一个插件,它由应用程序中的几个共享库构成,我们需要在应用程序运行时进行更新。出于性能原因,我们在卸载旧插件之前加载并开始使用新插件,只有当所有线程都使用旧插件时,我们才会卸载它。由于新插件和旧插件的库中有相同的符号,我们使用RTLD\u LOCAL创建了dlopen()。如果我们不使用新插件,内部函数会意外调用旧插件中的符号 一个插件库对另一个插件库创建的对象执行dynamic_cast()。这适用于HP-UX、AIX、Solaris和Windows,但不适用于Linux。据我所知,这是因

我们有一个插件,它由应用程序中的几个共享库构成,我们需要在应用程序运行时进行更新。出于性能原因,我们在卸载旧插件之前加载并开始使用新插件,只有当所有线程都使用旧插件时,我们才会卸载它。由于新插件和旧插件的库中有相同的符号,我们使用
RTLD\u LOCAL
创建了
dlopen()
。如果我们不使用新插件,内部函数会意外调用旧插件中的符号

一个插件库对另一个插件库创建的对象执行
dynamic_cast()
。这适用于HP-UX、AIX、Solaris和Windows,但不适用于Linux。据我所知,这是因为所有这些OSs(编译器)都使用类的名称来比较类型(在
dynamic_cast()
中),但Linux使用名称字符串地址来进行比较(以提高性能),而且每个库都有自己的
type_info
对象(因为它加载了
RTLD_LOCAL
)地址是不同的,因此相等的类型似乎与
动态\u cast()
不相等

是否有方法执行以下操作之一:

  • 仅加载
    type\u info
    对象,就像提供了
    RTLD\u GLOBAL
    一样
  • 使编译器使用类名比较而不是
    type\u 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.

好的,我们最后做的是解决这个问题

我们在想要
dynamic\u cast()
的类中添加了两个静态函数:

static MyClass* doNew();
static MyClass* doDynCast(MyBase*);
这些都是在cpp文件中实现的,cpp文件将
new
dynamic_cast()
type_info
对象保持在同一个库中,从而使
dynamic_cast()
能够解决问题

这个解决方案对于我们的具体情况来说已经足够了,但如果有人有更普遍的解决方案,我们会欢迎的


我们发现的另一个选项是将类的所有实现放在cpp文件中,这使得
typeinfo
符号只出现在一个库中,而所有其他库只引用它。这将导致成功的
dynamic\u cast()

不幸的是,由于type\u info结构是创建它们的库本地的弱符号,所以要使
dynamic\u cast
工作并不容易。但是,您可以尝试在实例化类vtable(和type_info)的位置进行操作;在GCC上,这可以通过确保仅在公共共享依赖项库中定义来实现。如果您的类没有非内联函数,那么创建一个伪函数来强制生成。但是请注意,我还没有测试过它,所以不能保证它能正常工作。此外,这依赖于编译器;我不知道英特尔的编译器做什么

当然,您可以使用类名实现自己的备用动态强制转换机制;有很多库也可以这样做,比如Qt