如何识别function/object在哪个模块中编译

How to identify in which module a function/object is compiled

我目前有一个项目,其中将不同的共享库 link 整合在一起。 这些库的用户能够将他们自己的共享库添加到项目中。在所有这些库中,人们可以这样写:

int a;
OBJECT(a)

double b;
OBJECT(b)

OBJECT 是一个宏,它收集有关 linked intdouble 或任何其他 type/class 的信息,并使它们可以通过公共所有其他共享库中的接口。它在所有库共享的 header 中定义。

我现在想做的是确定在哪个共享库中调用了宏。

目前我在所有共享库共享的 header 文件中使用类似的东西:

Module& getModule();

#define MODULE(name) Module& getModule() { \
    static Module mod{ #name }; \
    return mod; \
}

这引入了声明和宏来提供定义。然后在每个共享库中,我只在一个 .cpp 中调用宏,每次都使用不同的名称来引入定义。这为每个共享库定义了一个 static Module mod;,每个共享库都有自己的名称。 OBJECT 宏使用给定的 Module 在内部将此函数调用到 "register" 本身。通过这种方式,我可以获得使用 OBJECT 创建的所有 objects 的列表,按它们的 Module 排序(按它们所在的共享库排序)。

对于 MSVC,这工作正常。因为我没有在前面添加 _declspec(dllimport/dllexport),所以我强制 linker 到 link 到同一共享库中给出的定义。但是在 Linux(gcc) 下这不起作用,所有 OBJECT 宏都使用单个共享库中的定义,这意味着我无法再识别调用宏的库。

我知道,C++ 标准根本没有说明共享库,但我正在寻找的是一种 "as standard compliant as possible" 或至少尽可能可移植的方式。

我考虑过使用一个仅将 returns 和 "libary name" 作为字符串的宏。但这意味着如果你包含其他库的 headers,你需要确保它们要么不包含宏的定义,要么 include/definition 的顺序很重要,两者都是实践中很难确定。

还有其他(聪明的)方法可以解决这个问题吗?

一个简单的解决方案,即使在 Linux 上也能工作,就是将这个 Module 静态函数标识符放在你 link 的每个库中,但隐藏它以便默认不导出它:

#ifdef _WIN32
    #define DLL_LOCAL
#elif __linux__
    #define DLL_LOCAL  __attribute__ ((visibility ("hidden")))
#endif

#define MODULE(name) DLL_LOCAL Module& getModule() { \
    static Module mod{ #name }; \
    return mod; \
}