Как получилось, что некоторые функции C ++ с неопределенной компоновкой связей с C связью? - PullRequest
2 голосов
/ 20 мая 2010

Это то, что делает меня довольно озадаченным.

У меня есть файл 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 */ }

Реализации компилируются без предупреждений, но при связывании с кодом пользовательского интерфейса, который их вызывает, я получаю нормальный

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, вводит новую ошибку компоновки, так что она явно компилируется правильно.

Файл реализации никогда не модифицируется, только прототипы.

Ответы [ 2 ]

1 голос
/ 20 мая 2010

Ошибка указывает на то, что с файлом или заголовком реализации нет ничего плохого (как используется файлом реализации) - ошибка ссылки настоятельно предполагает, что фактически сгенерированные функции были созданы с помощью связи c ++. Это файл пользовательского интерфейса, который неправильно ищет C-Linkage версии функций. Исправление определений в заголовке исправляет вашу реализацию, чтобы соответствовать, вероятно, неправильным требованиям пользовательского интерфейса, а не наоборот.

Ваш файл пользовательского интерфейса - это файл .m или .c, ИЛИ, если ваш пользовательский файл - файл .cpp, у вас есть что-то вроде:

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

Конечно, если ваш файл пользовательского интерфейса представляет собой файл .c - вам нужно либо изменить его на cpp, ИЛИ явно определить функции с C-linkage, чтобы их можно было вызывать из C.

1 голос
/ 20 мая 2010

Могут ли имена функций конфликтовать с именами, объявленными в заголовке?

У вас возникает та же проблема, если вы даете функциям разные имена?

...