宏用于实现 dllexport/dllimport 开关

15
#if COMPILING_DLL
    #define DLLEXPORT __declspec(dllexport)
#else
    #define DLLEXPORT __declspec(dllimport)
#endif

我应该在哪里定义COMPILING_DLL

在这里看到:what does __declspec(dllimport) really mean?

听起来如果我不能使用相同的头文件,那么我根本无法使用加载时动态链接?

enter image description here


似乎你在某个地方犯了一些奇怪的错误,这里没有提到。放心,它应该可以工作,DLL非常有用。 - Öö Tiib
请访问 https://learn.microsoft.com/en-us/cpp/build/importing-into-an-application-using-declspec-dllimport?view=vs-2019 了解如何使用declspec(dllimport)将库导入应用程序中。 - GreatAndPowerfulOz
7个回答

21

另一个选择:

使用默认定义的宏 local 来处理项目。

您可以在以下位置查看项目中默认定义的宏 local:

属性 -> C/C++ -> 预处理器 -> 预处理器定义。

示例:

假设您的项目名称为:MyDLL

该项目默认的宏 local 为:MYDLL_EXPORTS

 #ifdef  MYDLL_EXPORTS 
    /*Enabled as "export" while compiling the dll project*/
    #define DLLEXPORT __declspec(dllexport)  
 #else
    /*Enabled as "import" in the Client side for using already created dll file*/
    #define DLLEXPORT __declspec(dllimport)  
 #endif

很遗憾的是,这个问题中最有用的代码并不在被接受的答案中。至少你在这里为我们提供了它 :) - kayleeFrye_onDeck
@kayleeFrye_onDeck 那段代码已经在问题中了。 - Öö Tiib
我已经创建了一个dll,但在另一个项目中使用时,MYDLL_EXPORTS仍然保持设置状态,而应该在此处取消设置。请问有人能告诉我这是为什么吗? - aki_sud

13

定义COMPILING_DLL=1的最佳位置是编译器的命令行。如果您使用Visual Studio IDE,则在项目属性中,选择 C/C++ ... 预处理器 ... 预处理器定义。

__declspec(dllimport)是微软对C ++的特定扩展。微软有出色的在线文档。


1
我将COMPILING_DLL添加到预处理器定义中,但它仍然抱怨“错误C2491:不允许dllimport函数的定义”。这毫无意义,因为Visual Studio现在甚至将正确的选项变灰。我添加了一张截图来说明这个问题。 - Blub
你应该将 COMPILING_DLL 添加到 DLL 项目的预处理器定义中。如果你在该项目的预编译头文件中包含了该头文件,请确保重新构建它。 - Öö Tiib

2
在DLL项目中,您可以添加一个#define(可以在头文件或项目属性中)来定义COMPILING_DLL。由于其他项目中不会设置这个宏(特别是如果您将其命名为比COMPILING_DLL更好的名称),因此#if指令将正常工作。请注意保留HTML标签。

2

在理想情况下,您(实际上是 Visual Studio)在构建 DLL 时将 COMPILING_DLL 定义为编译器的参数。因此,默认情况下会使用 __declspec(dllexport)。另一方面,在使用 DLL 的头文件时,您不需要定义这个参数,因此 DLLEXPORT 将默认评估为 __declspec(dllimport)


2
如果您使用 CMake 生成构建配置,则应该能够像使用 COMPILING_DLL 一样使用宏<projectname>_EXPORTS,其中projectname是通过 CMake 命令 project(projectname)定义的:

在检测到共享库编译时,将定义预处理器宏<target_name>_EXPORTS

来源

我测试过,使用 Visual Studio 2015 Express 的 MSVC 编译器和 Ninja 生成器在 Windows 上可以工作。

相关:CMake添加-Dlibname_EXPORTS编译定义


1
实际上,真正的问题是预处理指令。 您应该使用#ifdef而不是#if来测试变量是否真正定义(我们不关心定义值或是否存在)。
注意:我知道这个帖子已经过去1年了,但它仍然可能对将来遇到此问题的某些人有用。

只要伴随着defined!defined,你就可以使用#if,例如#if defined SOMETHING || !defined SOMETHING_ELSE - kayleeFrye_onDeck

1

您不能在头文件中以这种方式定义函数体。这是被__declspec(dllimport)禁止的。此限定符只能在函数声明上指定,而不能在定义上指定。

您必须将函数体移动到源文件中。

在头文件中:

extern DLLEXPORT void test2();

在 .cpp 文件中:
void test2()
{
   // ...
}

正如其他人所说,不要忘记将COMPILING_DLL添加到项目的预处理器定义中。


你提到的编译器错误来源(“error C2491:不允许定义dllimport函数'test2'”)是这个。但是似乎可以通过在代码中显式使用#define COMPILING_DLL来解决它,而不是将其添加到:项目>属性>C / C ++>预处理器>预处理器定义中。 - Masood Khaari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接