对于上下文:我有一个Java项目,它部分地由两个JNI库实现。为了以身作则,
libbar.so
取决于
libfoo.so
. 如果这些是系统库,
System.loadLibrary("bar");
会成功的。但由于它们是我的JAR附带的自定义库,我必须做一些
System.load("/path/to/libfoo.so");
System.load("/path/to/libbar.so");
libfoo必须先去,否则
libbar
找不到它,因为它不在系统库搜索路径中。
这已经很好地运行了一段时间,但是我现在遇到了一个问题
std::any_cast
正在投掷
std::bad_any_cast
尽管类型是正确的。我追踪到这两个库对该类型的typeinfo有不同的定义,并且它们在运行时不会被合并。这似乎是因为
System.load()
最终调用
dlopen()
具有
RTLD_LOCAL
而不是
RTLD_GLOBAL
.
我写这篇文章是为了展示这种行为而不需要JNI:
水电站
class foo { };
extern "C" const void* libfoo_foo_typeinfo();
食品cpp
#include "foo.hpp"
#include <typeinfo>
extern "C" const void* libfoo_foo_typeinfo()
{
return &typeid(foo);
}
钢筋cpp
#include "foo.hpp"
#include <typeinfo>
extern "C" const void* libbar_foo_typeinfo()
{
return &typeid(foo);
}
主.cpp
#include <iostream>
#include <typeinfo>
#include <dlfcn.h>
int main() {
void* libfoo = dlopen("./libfoo.so", RTLD_NOW | RTLD_LOCAL);
void* libbar = dlopen("./libbar.so", RTLD_NOW | RTLD_LOCAL);
auto libfoo_fn = reinterpret_cast<const void* (*)()>(
dlsym(libfoo, "libfoo_foo_typeinfo"));
auto libbar_fn = reinterpret_cast<const void* (*)()>(
dlsym(libbar, "libbar_foo_typeinfo"));
auto libfoo_ti = static_cast<const std::type_info*>(libfoo_fn());
auto libbar_ti = static_cast<const std::type_info*>(libbar_fn());
std::cout << std::boolalpha
<< (libfoo_ti == libbar_ti) << "\n"
<< (*libfoo_ti == *libbar_ti) << "\n";
return 0;
}
生成文件
all: libfoo.so libbar.so main
libfoo.so: foo.cpp
$(CXX) -fpic -shared -Wl,-soname=$@ $^ -o $@
libbar.so: bar.cpp
$(CXX) -fpic -shared -Wl,-soname=$@ $^ -L. -lfoo -o $@
main: main.cpp
$(CXX) $^ -ldl -o $@
在我的系统中,我得到
$ make
...
$ ./main
false
true
这是因为即使typeinfo地址不同,GCC的libstdc++也使用损坏的名称来表示相等。例如,在LLVM的libc++中,等式是基于typeinfo地址本身的,因此我得到:
$ make CXX="clang++ -stdlib=libc++"
$ ./main
false
false
如果我通过
RTLD U全球
相反,我明白了
true
true
如果我编辑
main.cpp
装载
利巴.so
首先,如果我告诉它在哪里可以找到,它也可以工作
李福索
:
$ LD_LIBRARY_PATH=. ./main
true
true
但基于本文顶部描述的原因,这两个都不是一个切实可行的解决办法。
这与
https://github.com/android-ndk/ndk/issues/533
但对于非动态类型,因此无法添加“键函数”来强制typeinfo成为强符号。我碰巧先在Android上重现了这个问题,但它不是Android特有的。