我正在使用C ++库,理想情况下,我将只保留标头。
此库的特定部分需要全局状态。
假设在此示例中,它需要一个字符串的全局向量。
我可以使用函数内的static
变量轻松实现此目的:
std::vector< std::string > & GetGlobalStrings( void )
{
static auto g = new std::vector< std::string >();
return *( g );
}
这非常适合使用该库的可执行文件。
现在由于某种原因,我还需要将该库打包在macOS框架中。
在该框架内,有编译后的代码将访问此全局状态。
与该框架链接的可执行文件也是如此。
显然这是行不通的,因为可执行文件和框架将对静态变量有单独的定义,因此使此全局状态不那么全局。
有什么方法可以方便地完成此任务吗?
答案 0 :(得分:1)
您可以强制将符号仅保存在一个文件中,例如:
override func viewDidLayoutSubviews() {
if(self.indicator != nil)
{
self.indicator.center = self.view.center
}
}
然后在您的一个框架cpp中,定义宏,然后再添加标题。
现在,如果您需要导出符号(主要是Windows,还需要隐藏可见性的Linux / macOS),则它会变得有些棘手,因为您需要另一个全局标志来说明您是否在框架中并激活导出/导入属性。
这绝对不是很好,但是至少要确保一个文件中只有一个静态变量实例。当然,也可以与静态库一起正常使用。
答案 1 :(得分:1)
那又怎么样:
// GlobalString.h
#include <string>
#include <vector>
#ifdef _MSC_VER
#ifdef GLOBAL_STRING_SRC
#define GLOBAL_STRING_DECLSPEC __declspec(dllexport)
#else
#define GLOBAL_STRING_DECLSPEC __declspec(dllimport)
#endif //GLOBAL_STRING_DECLSPEC
#endif // GLOBAL_STRING_SRC
inline EXPORT_SYMBOL std::vector<std::string>& GetGlobalStrings() noexcept
{
static std::vector<std::string> retval;
return retval;
}
然后编写一个.cpp文件,表明ODR使用您的GetGlobalStrings
定义。在Windows上,声明函数dllexport
是隐式的ODR使用。编译包含GlobalString.h
的cpp并将其链接到dll应该可以。
// GlobalSring.cpp
#define GLOBAL_STRING_SRC
#include <GlobalString.h>
inline
关键字保证了:如果GetGlobalStrings
使用了ODR,则链接器看到的来自不同编译单元的GetGlobalStrings
的多个定义将仅合并为一个。请放心,C ++保证内联函数中的静态变量也将被合并。请注意,除非声明定义为dllimport
,否则函数定义上的inline
是非法的。我对MacOS动态库不是很熟悉,但是它应该与带有-fvisibility = default标志的clang类似地工作。
使用C ++ 17时,可能还可以使用内联变量而不是函数:
inline EXPORT_SYMBOL std::vector<std::string> GlobalString;