我看到了这样的Qt源代码:
class Q_CORE_EXPORT QBasicAtomicInt
{
public:
...
};
哪个Q_CORE_EXPORT
宏定义如下:
define Q_DECL_IMPORT __declspec(dllimport)
那么__declspec(dllimport)
到底是什么意思?
__declspec
是Microsoft特定的属性,允许您指定存储类信息。((Nitpicker的角:但是,许多其他编译器供应商,例如GCC,现在都支持此语言扩展,以便与针对Microsoft编译器编写的已安装代码库兼容。有些甚至提供其他存储类属性。]
可以指定的两个存储类属性是__declspec
和dllimport
。这些向编译器指示分别从DLL导入或导出函数或对象。
更具体地说,它们定义了到客户端的DLL接口,而不需要模块定义(dllexport
)文件。大多数人发现使用这些语言扩展比创建DEF文件容易得多。
[出于明显的原因,.DEF
和__declspec(dllimport)
通常相互配对。使用__declspec(dllexport)
将符号标记为从DLL导出,然后使用dllexport
将该导出的符号导入另一个文件。
由于这个原因,并且因为在编译DLL时以及在使用DLL接口的客户端代码中通常都使用相同的头文件,所以在编译时定义宏自动解析为适当的属性说明符是一种常见的模式-时间。例如:
dllimport
然后标记所有应用#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
导出的符号。
大概是DLLEXPORT
宏所做的,解析为Q_CORE_EXPORT
或Q_DECL_IMPORT
。
Q_DECL_EXPORT
是一个存储类说明符,它告诉编译器在外部DLL中定义了函数,对象或数据类型。
函数或对象或数据类型是从具有相应__declspec(dllimport)
的DLL中导出的。
__declspec(dllexport)
告诉编译器通知链接器,这些符号需要放置在导出表中(编译.dll时)。当编译与.dll链接的程序时,__declspec(dllexport)
告诉编译器生成绝对的内存间接分支指令(链接程序将使用导入表中的指针地址填充该指令),而不是绝对直接分支指令(由于它无法修改指令,因此链接器会插入一个thunk的地址,然后创建thunk,在其内部,它会在导入表中放置对函数指针的间接调用)。这是代码大小和速度优化。导入库.lib告诉链接器将导入哪些符号,并用作创建导入表的指南。
__declspec(dllimport)
https://docs.microsoft.com/en-us/cpp/build/importing-function-calls-using-declspec-dllimport?view=vs-2019https://docs.microsoft.com/en-us/cpp/build/importing-data-using-declspec-dllimport?view=vs-2019
这意味着函数的定义在动态库中。有关更多详细信息和示例,请参考https://stackoverflow.com/a/4490536/7194773。