今天在使用 vs 做一个 dll 库,由于要是用 单件模式,在 .h 文件中声明了一个 static 的指针,在对应的cpp文件中定义该变量。导出的时候出现了一个错误:
错误 2error C2491: “SDK_functions::pinstance_”: 不允许 dllimport 静态数据成员 的定义
出现这个错误的原因是我擅自更改了 vs 自动为我建立的导出宏:
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 CYAPI_2013_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// CYAPI_2013_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef CYAPI_EXPORTS
#define CYAPI_API __declspec(dllexport)
#else
#define CYAPI_API __declspec(dllimport)
#endif
可以看到,我手动把对应的2013这几个字符去掉了,这就导致了 CYAPI_EXPORTS 这个宏没有定义,从而使用了 __declspec(dllimport)。__declspec(dllexport) 是用来导出的,为我这样写导出库的人所用; __declspec(dllimport) 是导入,为使用这个库的人所用。
在msdn 中说:不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。
而别人想使用我这个库的静态变量,就必须使用__declspec(dllimport) 才能导入 DLL 中使用的变量,所以与之对应就必须使用__declspec(dllexport)来导出这个变量。而对于一般变量而言就不需要了。