views:

85

answers:

2

This is something that makes me fairly perplexed.

I have a C++ file that implements a set of functions, and a header file that defines prototypes for them.

When building with Visual Studio or MingW-gcc, I get linking errors on two of the functions, and adding an 'extern "C"' qualifier resolved the error. How is this possible?

Header file, "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++ file, "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 */ }

The implementations compile without warnings, but when linking with the UI code that calls these, I get a normal

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 *

What really confuses me, now, is that only these two functions (HandleStart and CheckValid) seems to be built with C linkage. Explicitly adding "extern 'C'" declarations for only these two resolved the linking error, and the application builds and runs. Adding "extern 'C'" on some other function, such as HandleEnd, introduces a new linking error, so that one is obviously compiled correctly.

The implementation file is never modified in any of this, only the prototypes.

+1  A: 
David Sykes
Nope, no symbol conflict. Renaming "HandleStart" to "HandleStart__with__unique__name__xxyzz" or similar causes that function to fail to be resolved when linkage is unspecified, but it can be resolved if the prototype defines "C" linkage.
Christoffer
+1  A: 

The error indicates that nothing is wrong with your implementation file or header (as used by the implementation file) - the link error strongly suggests that the functions actually generated were generated with c++ linkage - Its the UI file thats incorrectly looking for the C-Linkage versions of the functions. Patching the definitions in the header is patching your implementation to conform to the probably incorrect demands of the UI, rather than the other way around.

Your UI file is either a .m or .c file, OR , if your UI file is a .cpp file you have dome something like:

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

Of course, if your UI file is a .c file - you either need to change it to cpp, OR explicitly define the functions with C-linkage so they can be called from C.

Chris Becke