C++ 在linux上加载多个类似的共享库

C++ 在linux上加载多个类似的共享库,c++,linux,gcc,ld,C++,Linux,Gcc,Ld,我正在编写创建“模型”的代码。模型是从XML文件创建的,它的部分表示是动态生成的C代码。此C代码动态编译到一个动态加载的共享库中(使用POCO共享库类)。共享库主要包含小函数,模型创建的一部分是填充指向这些函数的函数指针。这一切都很好。但是,同时创建多个模型会导致问题 我相信这与Linux上的动态加载工作方式有关,而且每个共享库都包含具有相同名称的函数。是PIC造成的吗?这些问题在从共享库函数检索数据时毫无意义地表现出来 所以问题是,如何在linux上加载包含相同函数名的多个(数千个)共享库 上

我正在编写创建“模型”的代码。模型是从XML文件创建的,它的部分表示是动态生成的C代码。此C代码动态编译到一个动态加载的共享库中(使用POCO共享库类)。共享库主要包含小函数,模型创建的一部分是填充指向这些函数的函数指针。这一切都很好。但是,同时创建多个模型会导致问题

我相信这与Linux上的动态加载工作方式有关,而且每个共享库都包含具有相同名称的函数。是PIC造成的吗?这些问题在从共享库函数检索数据时毫无意义地表现出来

所以问题是,如何在linux上加载包含相同函数名的多个(数千个)共享库


上述方法在windows上运行良好,在windows中,动态加载的库数据/函数似乎彼此完全隔离

首先,您可以
dlopen
数十万个共享对象。我的报告证明了这一点

然后,您还可以生成C代码,编译它,并
dlopen
共享对象,所有这些都来自同一个过程。My(2017年过时)(对于GCC,MELT提供了一种高级语言来扩展GCC)做到了这一点(My
manydl.c
示例也是如此)

但是,我认为不应该在它们中保留相同的(定义的)函数名。我建议避免这样做。你可以

  • 生成唯一的名称(因为生成了C代码,所以这是最好的、最可移植的、最简单的解决方案)

  • 使用一些
    -D
    标志进行编译,以
    #将这些名称定义为唯一的名称,因此源代码显然可能包含重复的名称;也就是说,如果生成的代码定义了
    foo
    函数,则将
    -Dfoo=foo_123
    (其中
    foo_123
    是全局唯一的)传递给编译它的
    gcc
    命令。(当然,对于
    “foo_123”
    ,您可以使用
    dlsym

  • 在生成的代码中添加函数属性。您还可以将
    -fvisibility=hidden
    传递给
    gcc

  • 只有静态函数(因此,名称无关紧要,可以重复),并且有一个
    构造函数
    函数以某种方式绑定函数(例如,将其指针存储在某个位置,例如在某个全局表中)

  • > p>您可以考虑通过<代码> RTLDIOpjix/Cux>。我不确定这是一个好主意(POCO可能不知道如何做到这一点)

    另外,我认为这与(在共享对象中,这是更好的,但不是绝对必需的;如果没有
    -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函数。但是,这些函数是内部模型类的一部分,这意味着更改它们的名称将导致相当大的内部更改。设置链接器标志可以避免所有这些。