2

これは私をかなり当惑させるものです。

関数のセットを実装する C++ ファイルと、それらのプロトタイプを定義するヘッダー ファイルがあります。

Visual Studio または MingW-gcc でビルドすると、2 つの関数でリンク エラーが発生し、「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 *

今、私を本当に混乱させているのは、これら 2 つの関数 (HandleStart と CheckValid) だけが C リンケージで構築されているように見えることです。これら 2 つのみに「extern 'C'」宣言を明示的に追加すると、リンク エラーが解決され、アプリケーションがビルドおよび実行されます。HandleEnd などの他の関数に「extern 'C'」を追加すると、新しいリンク エラーが発生するため、明らかに正しくコンパイルされます。

実装ファイルは、プロトタイプのみで変更されることはありません。

4

2 に答える 2

1

エラーは、実装ファイルまたはヘッダー(実装ファイルで使用されている)に問題がないことを示しています-リンクエラーは、実際に生成された関数がc++リンケージで生成されたことを強く示唆しています-そのUIファイルはC-Linkageを誤って探しています関数のバージョン。ヘッダーの定義にパッチを適用することは、その逆ではなく、UIのおそらく誤った要求に準拠するように実装にパッチを適用することです。

UIファイルは.mまたは.cファイルのいずれかです。または、UIファイルが.cppファイルの場合は、次のようなドームがあります。

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

もちろん、UIファイルが.cファイルの場合は、cppに変更するか、Cから呼び出すことができるようにCリンクを使用して関数を明示的に定義する必要があります。

于 2010-05-20T14:17:47.330 に答える
1

関数名がヘッダーで宣言された名前と競合する可能性はありますか?

関数に別の名前を付けても同じ問題が発生しますか?

于 2010-05-20T08:45:42.473 に答える