2012-01-11 4 views
0

Я хочу использовать некоторые классы C++ в общей библиотеке с C-связью. И у меня были следующие проблемы.C linkage и C++ заголовки

Если

#include <iostream> 
extern "C" 
{ 
void f(){} 
} 

компилируется и успешно, но f() не может быть найден в результате библиотеку.

Если

extern "C" 
{ 
#include <iostream> 
void f(){} 
} 

Я получил много ошибок компилятора (просто не знаю, как правильно перевести их на английском языке, то о шаблоне с C связи) на каждом вхождении ключевого слова «шаблон» C++ в iostream и включены заголовки ,

Что делать?

ответ

4

Первый вариант правильный. Только те, что существует в C, могут быть объявлены в блоке extern "C", а шаблоны и классы, безусловно, не принадлежат к этой категории. Вам нужно только убедиться, что ваша функция также объявлена ​​как extern "C" в заголовке, если вы используете компилятор C++. Это часто достигается путем написания

#ifdef __cplusplus 
// C++ declarations (for example classes or functions that have C++ objects 
//     as parameters) 

extern "C" 
{ 
#endif 

// C declarations (for example your function f) 

#ifdef __cplusplus 
} 
#endif 

в заголовке.

+0

Спасибо. Он отлично работал. – Alexander

0

Использование __declspec экспортировать функции, классы и т.д. ... также: http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx

И это один очень хороший: http://www.flounder.com/ultimateheaderfile.htm

+0

Это не переносимо, ОП не сказал, какой компилятор он использует. – filmor

+0

Да, забыл сказать. Я использую gcc 4.6.1 и Linux. – Alexander

+0

Вам не нужно использовать declspec (даже в Windows), а с помощью extern «C» он является кросс-совместимым с другими компиляторами C++, а также, возможно, с C-кодом. Если он строится на Windows в качестве платформы, вы должны использовать файл .def для объявления символа в таблице экспорта. – CashCow

2

Первый является правильным; системные заголовки (и большинство других заголовков) могут быть включены только в глобальную область, вне любых пространств имен, классов, функций или блоков спецификации ссылок. Есть вероятность вещи в <iostream>, что не было бы законным в extern "C", и даже если не было, имя коверкая для extern "C" почти наверняка отличается от C++, а сама библиотека была, несомненно, составлена ​​ , как extern "C++".

Как вы определяете f? Это может быть аналогичной проблемой: если исходный файл компилирует его как функцию extern "C++", тогда имя будет изменено иначе, чем в клиентских файлах, которые скомпилировали его как с функцией extern "C".

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

#if __cplusplus 
extern "C" { 
#endif 
void f(); 
// Other `extern "C"` functions... 
#if __cplusplus 
} 
#endif 

Затем включите этот заголовок во всех файлах, где функция f() используется, и в файле, где она определена.

 Смежные вопросы

  • Нет связанных вопросов^_^