C++ 在linux上加载多个类似的共享库
我正在编写创建“模型”的代码。模型是从XML文件创建的,它的部分表示是动态生成的C代码。此C代码动态编译到一个动态加载的共享库中(使用POCO共享库类)。共享库主要包含小函数,模型创建的一部分是填充指向这些函数的函数指针。这一切都很好。但是,同时创建多个模型会导致问题 我相信这与Linux上的动态加载工作方式有关,而且每个共享库都包含具有相同名称的函数。是PIC造成的吗?这些问题在从共享库函数检索数据时毫无意义地表现出来 所以问题是,如何在linux上加载包含相同函数名的多个(数千个)共享库C++ 在linux上加载多个类似的共享库,c++,linux,gcc,ld,C++,Linux,Gcc,Ld,我正在编写创建“模型”的代码。模型是从XML文件创建的,它的部分表示是动态生成的C代码。此C代码动态编译到一个动态加载的共享库中(使用POCO共享库类)。共享库主要包含小函数,模型创建的一部分是填充指向这些函数的函数指针。这一切都很好。但是,同时创建多个模型会导致问题 我相信这与Linux上的动态加载工作方式有关,而且每个共享库都包含具有相同名称的函数。是PIC造成的吗?这些问题在从共享库函数检索数据时毫无意义地表现出来 所以问题是,如何在linux上加载包含相同函数名的多个(数千个)共享库 上
上述方法在windows上运行良好,在windows中,动态加载的库数据/函数似乎彼此完全隔离 首先,您可以
dlopen
数十万个共享对象。我的报告证明了这一点
然后,您还可以生成C代码,编译它,并dlopen
共享对象,所有这些都来自同一个过程。My(2017年过时)(对于GCC,MELT提供了一种高级语言来扩展GCC)做到了这一点(Mymanydl.c
示例也是如此)
但是,我认为不应该在它们中保留相同的(定义的)函数名。我建议避免这样做。你可以
-D
标志进行编译,以#将这些名称定义为唯一的名称,因此源代码显然可能包含重复的名称;也就是说,如果生成的代码定义了foo
函数,则将-Dfoo=foo_123
(其中foo_123
是全局唯一的)传递给编译它的gcc
命令。(当然,对于“foo_123”
,您可以使用dlsym
)
-fvisibility=hidden
传递给gcc
构造函数
函数以某种方式绑定函数(例如,将其指针存储在某个位置,例如在某个全局表中)-fPIC
,dlopen
将不得不进行大量低效的重新定位)无关。它与Linux共享对象链接和加载有关。详情请阅读
另请参阅,并阅读。Poco SharedLibrary打开函数接受链接器标志。默认值为Poco::SharedLibrary::SHLIB_GLOBAL,对应于DLRTLD_GLOBAL;Poco::SharedLibrary::SHLIB_LOCAL,对应于RTLD_LOCAL。有关更多信息,请参阅
传递Poco::SharedLibrary::SHLIB_本地标志修复了该问题。感谢您的建议。我的第一个想法是赋予函数唯一的名称,但这需要在API中进行大量重写。然而,这个问题的真正答案要简单得多,幸运的是有一个控制符号解析方式的链接器标志,即RTLD_全局和RTLD_局部。默认值为RTLD_全局。将加载程序标志设置为RTLD_LOCAL修复了该问题!我确实提到了
RTLD_LOCAL
,但我认为这不是一个好办法。我不明白为什么生成唯一名称会改变API(该名称对dlsym非常有用),除非一个生成的共享对象直接从另一个生成的共享对象调用函数。为什么您认为RTLD_LOCAL不是一个好方法?共享库不包含任何对象,但包含简单的C函数。但是,这些函数是内部模型类的一部分,这意味着更改它们的名称将导致相当大的内部更改。设置链接器标志可以避免所有这些。