2

这是让我相当困惑的事情。

我有一个实现一组函数的 C++ 文件,以及一个为它们定义原型的头文件。

使用 Visual Studio 或 MingW-gcc 构建时,我在其中两个函数上出现链接错误,添加“extern "C"”限定符解决了该错误。这怎么可能?

头文件,“some_header.h”:

// Definition of struct DEMO_GLOBAL_DATA omitted

DWORD WINAPI ThreadFunction(LPVOID lpData);
void WriteLogString(void *pUserData, const char *pString, unsigned long nStringLen);
void CheckValid(DEMO_GLOBAL_DATA *pData);
int HandleStart(DEMO_GLOBAL_DATA * pDAta, TCHAR * pLogFileName);
void HandleEnd(DEMO_GLOBAL_DATA *pData);

C++ 文件,“some_implementation.cpp”

#include "some_header.h"

DWORD WINAPI ThreadFunction(LPVOID lpData) { /* omitted */ }
void WriteLogString(void *pUserData, const char *pString, unsigned long nStringLen) { /* omitted */ }
void CheckValid(DEMO_GLOBAL_DATA *pData) { /* omitted */ }
int HandleStart(DEMO_GLOBAL_DATA * pDAta, TCHAR * pLogFileName) { /* omitted */ }
void HandleEnd(DEMO_GLOBAL_DATA *pData) { /* omitted */ }

实现编译时没有警告,但是当与调用这些的 UI 代码链接时,我得到一个正常的

error LNK2001: unresolved external symbol "int __cdecl HandleStart(struct _DEMO_GLOBAL_DATA *, wchar_t *)
error LNK2001: unresolved external symbol "void __cdecl CheckValid(struct _DEMO_MAIN_GLOBAL_DATA *

现在真正让我感到困惑的是,似乎只有这两个函数(HandleStart 和 CheckValid)是用 C 链接构建的。仅为这两个显式添加“extern 'C'”声明解决了链接错误,并且应用程序构建并运行。在其他一些函数上添加“extern 'C'”,例如 HandleEnd,会引入一个新的链接错误,因此显然编译正确。

实现文件永远不会被修改,只有原型。

4

2 回答 2

1

函数名称是否会与标头中声明的名称冲突?

如果你给函数起不同的名字,你会遇到同样的问题吗?

于 2010-05-20T08:45:42.473 回答
1

该错误表明您的实现文件或标头(由实现文件使用)没有任何问题 - 链接错误强烈表明实际生成的函数是使用 c++ 链接生成的 - 它的 UI 文件错误地寻找 C-Linkage函数的版本。修补标头中的定义是修补您的实现以符合 UI 可能不正确的要求,而不是相反。

您的 UI 文件是 .m 或 .c 文件,或者,如果您的 UI 文件是 .cpp 文件,您的圆顶文件类似于:

// ui.cpp
extern "C" {
#include "some_header.h"
}

当然,如果您的 UI 文件是 .c 文件 - 您要么需要将其更改为 cpp,要么使用 C-linkage 显式定义函数,以便可以从 C 调用它们。

于 2010-05-20T14:17:47.330 回答