要明确: 我知道下面的例子演示了一个dll-dependancy,即一个库不是自包含的,但依赖于另一个库来运行。
假设我正在创建一个运行时库,Utility.dll,它包含一般性的各种有用功能。 我创建一个头文件Utility.h,以包含在需要使用Utility.dll的其他文件中。 头文件看起来像
#ifndef _UTILITY_H
#define _UTILITY_H
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
DLL_EXPORT void foo();
DLL_EXPORT void foo2();
....
#endif
当我将源代码文件Utility.cpp编译成机器代码(进入Utility.dll)时,我确保定义了BUILD_DLL,因此DLL_EXPORT被__declspec(dllexport)替换。这使得函数可以导出到.dll文件。 每当我包含头部Utility.h并链接到导入库(MS VS的Utility.lib,g ++的libUtility.a)并且不定义BUILD_DLL时,Utility.h中的函数声明开始于改为__declspec(dllimport),告诉编译器函数是从.dll导入的(可以这么说)。
现在,假设我还在构建另一个库MyLibrary.dll,它希望使用Utility.dll中的一些有用功能。类似地,我将创建MyLibrary.h作为
#ifndef _MYLIBRARY_H
#define _MYLIBRARY_H
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
DLL_EXPORT void myLibraryFunc1();
....
#endif
当我将MyLibrary.cpp编译成MyLibrary.dll时,我包括Utility.h,并且还链接到Utility导入库。
这会引导我们进入问题: 由于我在编译MyLibrary.dll时也定义了BUILD_DLL,这意味着Utility.h中的函数声明也会读取
__declspec(dllexport) void foo();
__declspec(dllexport) void foo2();
....
不
__declspec(dllimport) void foo();
__declspec(dllimport) void foo2();
当我们为MyLibrary.h编译MyLibrary.dll和__declspec(dllexport)中的函数声明时,我们不希望它是__declspec(dllimport)吗?
答案 0 :(得分:2)
这正是您通常不会命名此类BUILD_DLL
,而是BUILD_UTILITY
和BUILD_MYLIBRARY
或类似名称的原因。同样,declspec宏不应该是DLL_EXPORT
,而是UTILITY_EXPORT
和MYLIBRARY_EXPORT
(或者UTILITY_API
和MYLIBRARY_API
)。