使用dllexport和特定函数名称时未解析的外部符号

Tre*_*edd 2 c++ dll dllexport

编辑

为了解决这个问题,我将以下内容添加到头文件的开头:

#ifdef GetMessage
#undef GetMessage
static inline BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
) {
#if UNICODE
return ::GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
#else
return ::GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
#endif
}
#endif
Run Code Online (Sandbox Code Playgroud)

我正在从以下代码创建一个C++ DLL(使用Visual Studio 2008):

头文件:

#include <windows.h> // Edit: This is the culprit.
class __declspec(dllexport) TestBaseClass
{
protected:
   char m_Message[512];
public:
   TestBaseClass();
   virtual char* GetMessage(void) = 0;
};

class __declspec(dllexport) TestDerivedClass : public TestBaseClass
{
public:
   TestDerivedClass();
   virtual char* GetMessage(void);
};
Run Code Online (Sandbox Code Playgroud)

CPP文件:

TestBaseClass::TestBaseClass()
{
}

TestDerivedClass::TestDerivedClass() : TestBaseClass()
{
}

char* TestDerivedClass::GetMessage(void)
{
   sprintf(m_Message, "This is a Message");
   return m_Message;
}
Run Code Online (Sandbox Code Playgroud)

当我去编译DLL时,我收到一个链接器错误:

错误LNK2001:未解析的外部符号"public:virtual char*__thiscall TestDerivedClass :: GetMessageA(void)"(?GetMessageA @ TestDerivedClass @@ UAEPADXZ)

如果我将"GetMessage"的每个实例更改为其他内容(例如"TestFunc"),我就不会收到链接器错误.

主要问题:为什么我不能使用"GetMessage"作为我的函数名?

次要问题:有没有办法解决链接器错误,并在我的类中保留"GetMessage",如当前定义的那样?

Han*_*ant 5

这是非常标准的预处理器损失.您的标识符正在被宏破坏.它位于Windows标头内,它将winapi GetMessage()函数重命名为GetMessageA或GetMessageW,具体取决于是否定义了UNICODE.

选择其他名称或使用#undef GetMessage


Ada*_*eld 5

这是由于 Windows 标头中的一个怪癖。当您使用 时#include <windows.h>,它是或#define的符号,具体取决于您是否启用了 Unicode 支持(更具体地说,如果定义了宏)——请参阅Windows API 中的 Unicode函数原型的约定以获取更多信息。GetMessageGetMessageAGetMessageWUNICODE

要解决此问题,您有几个选择:

  • 不要包含 Windows 标头
  • NOMSG在包含之前定义宏<windows.h>——这将抑制各种与消息相关的函数和宏的声明
  • #undef GetMessage 在你的类定义之前
  • 将您的函数重命名为其他名称