Czy extern " C " jest wymagany tylko w deklaracji funkcji?

Napisałem funkcję C++, którą muszę wywołać z programu C. Aby uczynić ją możliwą do wywołania z C, podałem extern "C" w funkcji deklaracja. Następnie skompilowałem kod C++, ale kompilator (Dignus Systems/C++) wygenerował zniekształconą nazwę dla funkcji. Więc najwyraźniej nie uszanował extern "C".

Aby to rozwiązać, dodałem extern "C" do definicji funkcji . Następnie kompilator wygenerował nazwę funkcji, którą można wywołać z C.

Technicznie rzecz biorąc, extern "C" musi być tylko określona w deklaracji funkcji. Czy to prawda? (The C++ FAQ Lite ma tego dobry przykład.) Czy należy go również określić w definicji funkcji?

Oto przykład, aby to zademonstrować:

/* ---------- */
/* "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...
}

mój problem może być wynikiem nieprawidłowego kodowania czegoś lub znalazłem błąd kompilatora. W każdym razie chciałem skonsultować się ze stackoverflow, aby upewnić się, że wiem, który jest technicznie "right" way.

Author: Wolfgang, 2009-09-04

6 answers

'extern "C" ' nie powinien być wymagany na definicji funkcji, o ile deklaracja ją posiada i jest już widoczna w kompilacji definicji. Standard określa konkretnie (specyfikacje połączeń 7.5/5):

Funkcja może być zadeklarowana bez specyfikacji powiązania po wyświetleniu jawnej specyfikacji powiązania; powiązanie wyraźnie określone we wcześniejszej deklaracji nie ma wpływu na taką deklarację funkcji.

Jednak Ja ogólnie rzecz biorąc, należy również umieścić 'extern "C" 'Na definicji, ponieważ w rzeczywistości jest to funkcja z zewnętrznym połączeniem "C". Wiele osób nie lubi, gdy zbędne, zbędne rzeczy są na deklaracjach( np. umieszczanie virtual na nadpisywaniu metod), ale ja nie jestem jednym z nich.

 30
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-04 19:00:05

Edit:
Chyba źle zrozumiałem pytanie. W każdym razie próbowałem:


// 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);

Użycie polecenia nm do wyświetlenia symboli ze skompilowanego pliku:


linuxuser$ nm foo.o
00000006 T _Z4testi
         U __gxx_personality_v0
00000000 T foo

To wyraźnie sugeruje, że nazwa funkcji zadeklarowanej jako extern " C "nie jest zniekształcona, a słowo kluczowe extern" C " nie jest wymagane w definicji.
Gdyby wymagało to, aby każdy kod biblioteki C napisany bez extern " C " byłby bezużyteczny w programach C++.

 2
Author: sud03r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-04 19:48:04

Właśnie napotkałem tę sytuację... Niezbyt przyjemne doświadczenie.

W jednym z moich plików c:

void unused_isr(void) {}
void ADC_IRQHandler(void)     __attribute__ ((weak, alias("unused_isr"))); 

Następny gdzieś w pliku cpp zdefiniowałem:

void ADC_IRQHandler(void) {                                                                                  
    ...
}

I zapomniałem zmienić deklarację forward na:

void ADC_IRQHandler(void);

Zajęło mi trochę czasu zanim zorientowałem się, że robię wszystko dobrze w odniesieniu do konwersji reklam, ale nie dodałem "extern C" do definicji!

extern "C" void ADC_IRQHandler(void) {                                                                                  
    ...
}
Tylko moje dwa grosze, dlaczego może się przydać w pewne okoliczności, aby mieć zwyczaj, aby dodać go do definicji, jak również.
 1
Author: Anne van Rossum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-07 09:21:42

Myślę, że należy to tutaj wyjaśnić, ponieważ właśnie miałem podobny problem i zajęło mi trochę czasu, aby to wyjaśnić w mojej głowie, tylko Brooks Moses poruszył to właściwie i myślę, że należy to powiedzieć jaśniej ...

Podsumowując nagłówek może cię wyrzucić, kompilator widzi tylko plik cpp i jeśli nagłówek nie jest dołączony z extern "C" z powrotem do twojego cpp (co zwykle widzę), to extern "C" będzie musiał być gdzieś w pliku cpp (albo w pliku cpp). definition, or another declaration) więc kompilator CXX może wiedzieć, aby zrobić to z C linkage, kompilator nie dba o nagłówek, tylko linker.

 1
Author: othane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-21 04:04:03

extern "C" wokół definicji nie jest wymagane. Możesz ujść na sucho po prostu umieszczając to wokół deklaracji. Jedna uwaga w twoim przykładzie...

#ifdef __cplusplus
extern "C" {
#endif

/* Function declaration */
void foo(int);

#ifdef __cplusplus
}
#endif

Twój kod szuka makra preprocesora " __cplusplus".

Chociaż jest powszechnie zaimplementowany, w zależności od kompilatora, może to być zdefiniowane lub nie. W twoim przykładzie używasz również extern "C" wokół deklaracji, ale tam nie sprawdzasz pod kątem makra " __cplusplus", dlatego podejrzewam, że zadziałało raz ty to zrobiłeś.

zobacz poniższe komentarze - standard C++ wymaga zdefiniowania makra __cplusplus przez preprocesor.

 1
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-04 05:03:38

Powinno być w pobliżu obu. Kompilator musi wiedzieć, aby używać nazwy symbolu C i wywoływać konwencje podczas kompilacji witryn wywołujących (które mogą widzieć tylko deklarację), a kompilator musi również wiedzieć, aby generować nazwę symbolu C i używać konwencji wywołujących C podczas kompilacji samej definicji funkcji (która może nie widzieć żadnych innych deklaracji).

Teraz, jeśli masz deklarację extern-C, która jest widoczna z jednostki tłumaczenia, w której istnieje definicja, możesz być w stanie ujść na sucho z pominięciem extern-C z definicji, ale nie wiem tego na pewno.

 0
Author: Tyler McHenry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-04 18:32:30