在函数声明之前添加预处理程序变量意味着什么?

问题描述 投票:0回答:1

我正在阅读Dear ImGui API,我想知道在这样的函数声明之前添加预处理器变量(在这里是[[IMGUI_API)是什么意思:

#ifndef IMGUI_API #define IMGUI_API #endif ... namespace ImGui { ... IMGUI_API float GetWindowWidth(); ... };
提前感谢!
c++ preprocessor function-declaration
1个回答
1
投票
[就像汉斯·帕桑(Hans Passant)所说-它不会总是空的。

动态共享库(和Windows中的DLL)的主要属性之一是库的内部符号不向用户公开。在GCC中,这是通过在构建库时在命令行上将默认符号可见性指定为“隐藏”来完成的。但是,这会使所有符号(包括您希望用户调用的符号)都隐藏起来,从而产生不希望的效果,从而使您的库实际上无效。

GCC提供了一种手动控制可见性的方法-__attribute__((visibility("default")))。这会将功能标记为具有默认可见性,这意味着它将由DSO公开。此属性在函数声明之前指定。

这会产生一个新问题-库用户在包含头文件时不需要/不希望在库函数中指定此属性。当用户包含标题时,应删除这些定义,仅保留裸函数声明。

有两种解决方法-拥有标头的两个副本,或者在编译前使用预处理程序更改代码。大多数(几乎所有)库程序员都选择后者,因为很难同步同一文件的两个副本。

ImGui的作者实现后一种方法的方式非常优雅-而不是像这样定义内联的API标记:

#ifdef IMGUI_API_BUILD #define IMGUI_API __attribute__((visibility("default"))) #else #define IMGUI_API #endif

他们的定义如下:

#ifndef IMGUI_API #define IMGUI_API #endif

如果未覆盖该符号,则将符号定义为默认值。

这的天才实际上是在编译过程中-通过在命令行上指定IMGUI_API的定义,他们可以更改代码的行为,而无需将其构建过程的元素暴露给世人。

他们所要做的就是将-D IMGUI_API=__attribute((visibility("default")))添加到编译器命令行,并且头文件神奇地将每个API函数标记为从共享库中导出。

实际上,他们可以将定义更改为所需的任何值,而无需在其他程序员以这种方式使用的头文件中公开该细节。调试信息,其他功能选项,指定热/冷路径信息...所有这些都可以在命令行上指定,而无需将该信息放入头文件中。

编辑:

现在看他们的代码,似乎他们还没有意识到这一点,并且为Linux创建了一个非常强大的共享库解决方案,毫无意义。尽管如此,以上所有内容仍然有效-其他库也可以执行相同的操作。

© www.soinside.com 2019 - 2024. All rights reserved.