c++ - 如何识别函数/对象在哪个模块中编译

标签 c++ shared-libraries cross-platform

我目前有一个项目,其中不同的共享库链接在一起。 这些库的用户能够将他们自己的共享库添加到项目中。在所有这些库中,可以编写如下内容:

int a;
OBJECT(a)

double b;
OBJECT(b)

OBJECT 是一个宏,它收集有关链接的 intdouble 或任何其他类型/类的信息,并通过一个通用的方式使它们可用所有其他共享库中的接口(interface)。它在所有库共享的 header 中定义。

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

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

Module& getModule();

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

这引入了声明和宏来提供定义。然后在每个共享库中,我只在一个 .cpp 中调用宏,每次都使用不同的名称来引入定义。这为每个共享库定义了一个static Module mod;,每个都有自己的名字。 OBJECT 宏在内部调用此函数以向给定的 Module“注册”自身。这样我就可以获得使用 OBJECT 创建的所有对象的列表,按它们的 Module 排序(按它们所在的共享库排序)。

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

我知道,C++ 标准根本没有提及共享库,但我正在寻找的是一种“尽可能符合标准”或至少尽可能可移植的方式。

我考虑过使用一个仅将“库名称”作为字符串返回的宏。但这意味着如果您包含其他库的 header ,则需要确保它们不包含宏的定义,或者包含/定义的顺序很重要,这两者在实践中都很难确定。

有没有其他(聪明的)方法来解决这个问题?

最佳答案

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

#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; \
}

关于c++ - 如何识别函数/对象在哪个模块中编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39698846/

相关文章:

c++ - 类对象还是指向它们对象的指针?类对象组合与实现

c - C 中的共享库和动态库有什么区别?

c++ - 编写库时是否应将可见性/导出宏应用于模板?

仅 C++ 前端编译器(将 C++ 转换为 C)

Java 跨平台 vlcj/libvlc Mac/Windows

c++ - memset() 的意外行为

c++ - 在 dynamic_casting 之后删除指针是否安全?

c++ - LLVM IR 生成的代码到 native 代码

c++ - waf 找不到现有库

Mac、Linux 和 PC (Redux) 上用于 Mono 的 Winforms