首页 > 解决方案 > dllexport 意外不会导致引用项目中的链接器错误

问题描述

根据我的理解,我遇到了一些应该导致链接器错误的行为。

我有两个 C++ 项目MyLibMyLibTestsMyLib是一个 windows dll 项目。在那个项目中有一个头文件Declspec.h

// Declspec.h
#pragma once
#define NATIVE_API __declspec(dllexport)
#define NATIVE_API_CALL __cdecl

它用于注释必须导出的函数(以便测试它们)。

现在有几个头文件声明了函数,例如GUID.h(我删掉了不必要的部分):

// GUID.h
NATIVE_API GUID newGuid();

及其相关的源文件,例如GUID.cpp

// GUID.cpp
GUID newGuid()
{
    GUID g;
    (void)CoCreateGuid(&g);
    return g;
}

MyLib构建GUID.cpp,到目前为止一切都很好。现在MyLibTests引用 dll 并调用该newGuid()函数。为此,MyLibTests中包含了完全相同的GUID.h。代码编译,看起来运行正常。这是我不明白的一点。通过包含GUID.h,我们可传递地包含将宏解析为 的 Declspec.h ,这意味着应该再次导出该函数(这本身已经是错误的)。我假设这需要一个翻译单元(此处为GUID.cpp)中可用的定义才能允许导出。但是由于NATIVE_API__declspec(dllexport)dllexportGUID.cpp不是作为MyLibTests项目的一部分构建的,我希望链接器错误而不是成功构建

据我所知,Declspec.h看起来像这样:

// Declspec.h
#ifdef SOME_PROJECT_DEPENDEND_MACRO
#   define NATIVE_API __declspec(dllexport)
#else
#   define NATIVE_API __declspec(dllimport)
#endif

并且SOME_PROJECT_DEPENDEND_MACRO是在提供该功能的项目的项目文件中声明的宏。这样,定义项目中的所有包含都会获得dllexport签名,而所有引用项目都包含带有dllimport签名的头文件(因此不要在自己的翻译单元中查找定义)。

尽管两个项目中的所有功能总是被dllexport编辑,为什么两个项目都能成功编译(并运行)?

标签: c++visual-c++dllimportdllexport

解决方案


大多数编译器可以选择只创建预处理文件,而不是实际编译和创建目标文件。

例如,Visual Studio 编译器有/E 选项。然后,您可以检查预处理文件以查看NATIVE_API测试源文件中实际预处理的内容。当与其他选项结合使用时,您可以将预处理器输出写入文件并检查它。与您期望的定义相比,该定义可能来自其他地方。


推荐阅读