Я записал функцию C++, которую я должен вызвать из программы C. Для создания этого вызываемым из C я указал extern "C"
на объявлении функции. Я затем скомпилировал код C++, но компилятор (Системы/C++ Dignus) генерировал скорректированное имя для функции. Так, это, по-видимому, не соблюдало extern "C"
.
Для разрешения этого добавил я extern "C"
к функциональному определению. После этого компилятор генерировал имя функции, которое является вызываемым от C.
Технически, extern "C"
только потребности, которые будут указаны на объявлении функции. Действительно ли это правильно? (FAQ C++ имеет хороший пример этого.) Необходимо ли также указать его на функциональном определении?
Вот пример для демонстрации этого:
/* ---------- */
/* "foo.h" */
/* ---------- */
#ifdef __cplusplus
extern "C" {
#endif
/* Function declaration */
void foo(int);
#ifdef __cplusplus
}
#endif
/* ---------- */
/* "foo.cpp" */
/* ---------- */
#include "foo.h"
/* Function definition */
extern "C" // <---- Is this needed?
void foo(int i) {
// do something...
}
Моей проблемой может быть результат неправильного кодирования чего-то, или я, возможно, нашел ошибку компилятора. В любом случае я хотел консультироваться с stackoverflow, чтобы удостовериться, что я знаю, который является технически "правильным" путем.
' extern "C"
' не должен требоваться в определении функции, если он есть в объявлении и уже замечен при компиляции определения. В стандарте конкретно говорится (7.5 / 5 Спецификации связывания):
Функция может быть объявлена без спецификации связывания после того, как явная спецификация связывания была обнаружена; на связь, явно указанную в предыдущем объявлении, такое объявление функции не влияет.
Тем не менее, я обычно добавляю ' extern «C»
' в определение, потому что это фактически функция с внешней связью "C". Многие люди ненавидят, когда в объявлениях используется ненужный, избыточный материал (например, установка virtual
на переопределения методов), но я не один из них.
Редактировать:
Похоже, я неправильно понял вопрос.
В любом случае, я попробовал:
// foo.cpp
/* Function definition */
#include "foo.h"
void foo(int i) {
//do stuff
}
void test(int i)
{
// do stuff
}
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
/* Function declaration */
void foo(int);
#ifdef __cplusplus
}
#endif
void test(int);
Используя команду nm
, чтобы просмотреть символы из скомпилированного файла:
linuxuser$ nm foo.o
00000006 T _Z4testi
U __gxx_personality_v0
00000000 T foo
Это явно предполагает, что имя функции, объявленной как extern «C», не искажено, а extern » Ключевое слово C "не требуется при определении.
Если бы для этого требовалось, что каждый код библиотеки C, написанный без extern «C», был бы непригоден для использования в программах на C ++.
extern «C»
вокруг определения не требуется. Вы можете уйти, просто поместив это в декларацию. Одно примечание в вашем примере ...
#ifdef __cplusplus
extern "C" {
#endif
/* Function declaration */
void foo(int);
#ifdef __cplusplus
}
#endif
Ваш код ищет макрос препроцессора « __ cplusplus
».
Хотя это обычно реализуется, в зависимости от вашего компилятора это может быть определено или не определено. В вашем примере вы также используете extern «C»
вокруг объявления, но там вы не проверяете макрос « __ cplusplus
», поэтому я подозреваю это сработало, как только вы это сделали.
См. Комментарии ниже - Стандартный C ++ требует, чтобы макрос __ cplusplus
был определен препроцессором.
Он должен быть где-то рядом. Компилятору необходимо знать, как использовать имя символа C и соглашения о вызовах при компиляции сайтов вызовов (которые могут видеть только объявление), а компилятор также должен знать, как сгенерировать имя символа C и использовать соглашения о вызовах C при компиляции само определение функции (которое может не видеть никаких других объявлений).
Теперь, если у вас есть объявление extern-C, которое видно из единицы перевода, в которой существует определение, вы можете уйти, оставив extern-C из определения, но я этого точно не знаю.