Frage zu extern "C"
-
pumuckl schrieb:
Und kann man das so schreiben bzw. sollte man es so machen?
Nein. Sollte man nicht. #define cplusplus bzw. #define __cplusplus werden vom Compiler gemacht, das solltest du selber garnicht machen.
wtf?
Was heißt denn hier "machen"?
Das vordefinierte Macro heißt __cplusplus. Ohne Doppel-Unterstrich taucht das nicht im C++ Standard auf.
-
Ich hab das ganze jetzt mal von C nach C++ ausprobiert. Meine Funktionen werden ohne Probleme ausgeführt.
Aber ich bekomme immer diese Warnungen:
[C++ Warnung] Unit1.c(7): W8065 Aufruf der Funktion 'function' ohne Prototyp [C++ Warnung] Unit1.c(9): W8065 Aufruf der Funktion 'function_2' ohne Prototyp [C++ Warnung] Unit1.c(11): W8065 Aufruf der Funktion 'system' ohne Prototyp
Wenn ich in my_functions.cpp nicht schreibe:
void function();
void function_2();Wieso muss ich in my_functions.cpp auch nochmal die Prototypen definieren?
Das habe ich doch eigentlich schon in my_header.h gemacht.main.c
#include <stdio.h> #include "my_header.h" int main(int argc, char* argv[]) { function(); printf("\n"); function_2(); system("PAUSE"); }
my_header.h
#ifndef my_header #define my_header #ifdef __cplusplus extern "C" // Ermöglicht die Verwendung von C++ Funktionen in // C Programmen { void function(); void function_2(); } #endif #endif
my_functions.cpp
#include "my_header.h" #include <iostream> using namespace std; void function(); void function_2(); void function() { cout<<"ok"; } void function_2() { cout<<"funktion 2"; }
-
-.- Wenn ich mein Projekt abspeichere kommt wieder diese Prototyp Warnung, da hab ich mich wohl zu früh gefreut ...
Obwohl ich in my_function.cpp die Funktionen definiert habe.
-
#ifndef my_header #define my_header #ifdef __cplusplus extern "C" // Ermöglicht die Verwendung von C++ Funktionen in // C Programmen { void function(); void function_2(); } #endif #endif
Denk mal darüber nach, was hier beim Compiler ankommt, wenn __cplusplus nicht definiert ist. Richtig: garnichts.
Und dann vergleiche nochmal mit den vorangegangenen Beiträgen, insbesondere verfolge die Diskussion "Warum nimmt man #endif mit in die geschweifte Klammer?"
-
externC schrieb:
my_header.h
#ifndef my_header #define my_header #ifdef __cplusplus extern "C" // Ermöglicht die Verwendung von C++ Funktionen in // C Programmen { void function(); void function_2(); } #endif #endif
Das ist ja auch falsch so. Der C Compiler sieht davon GAR nix, weil der Präprocessor alles rausschmeißt; denn __cplusplus ist ja beim C Compiler nicht definiert. Dementsprechend fehlen Dir die Funktionsdeklarationen ("Prototypen" in C-Sprech) und der C-Compiler warnt Dich, dass Du Funktionen später aufrufst, die er noch gar nicht kennt.
Richtig:
... #ifdef __cplusplus extern "C" { [b]#endif[/b] ... [b]#ifdef __cplusplus[/b] } #endif ...
-
Wieder die Prototyp Fehlermeldung.
Ich versteh nicht was da jetzt schon wieder falsch sein soll. (Naja falsch vielleicht nicht denn es Kompiliert ja und läuft. (Ein Lehrer sagte mal "Das sind nur Warnungen das ist nicht so schlimm", aber ob das nicht so schlimm ist da zweifel ich irgendwie dran, den die Warnung wird ja nicht zum Spass ausgegeben.)
main.c
#include <stdio.h> #include "my_header.h" int main() { function(); function_2(); system("PAUSE"); return 0; }
my_header.h
#ifndef my_header #define my_header #ifdef __cplusplus extern "C" { #endif void function(); void function_2(); #ifdef __cplusplus } #endif #endif
my_functions.cpp
#include "my_header.h" #include <iostream> using namespace std; void function() { cout<<"ok"; } void function_2() { cout<<"function_2"; }
-
pumuckl schrieb:
- Die Definition muss in C-Code nicht weiter markiert werden, in C++-Code muss sie auch wieder als extern "C" markiert werden.
Edit: Wobei ... bei mir läuft das Programm fehlerfrei und ohne Warnungen beim Erstellen:
cl -c main.c
cl -c /EHsc my_functions.cpp
link main.obj my_functions.objerstellt main.exe ohne Warnungen und Fehler ...
-
externC schrieb:
Wieder die Prototyp Fehlermeldung.
Ich versteh nicht was da jetzt schon wieder falsch sein soll. (Naja falsch vielleicht nicht denn es Kompiliert ja und läuft. (Ein Lehrer sagte mal "Das sind nur Warnungen das ist nicht so schlimm", aber ob das nicht so schlimm ist da zweifel ich irgendwie dran, den die Warnung wird ja nicht zum Spass ausgegeben.)
Das ist richtig. Zum Spaß sind die nicht da. Diese Warnung richtig interpretiert heißt: "Ich kann nicht überprüfen, ob es die Funktion gibt und/oder ob Du sie mit den richtigen Parametern aufrufst". Du bist also auf Dich allein gestellt und wenn Du etwas falsch machst, dann gibt Dir das Programm Grütze aus oder schmiert ab.
externC schrieb:
my_header.h
#ifndef my_header #define my_header #ifdef __cplusplus extern "C" { #endif void function(); void function_2(); #ifdef __cplusplus } #endif #endif
Du solltest für eigene Macros immer Namen verwenden, die mit einem Großbuchstaben anfangen und keine kleinen Buchstaben enthalten. Auch übermäßiger Gebrauch von Unterstrichen (am Anfang oder irgendwo zweimal hintereinander) sollte man für eigene Namen nicht verwenden, da die reserviert sind.
Der Haken hier ist, dass eine leere Parameter-Klammer in C90 etwas anderes bedeutet als in C++:
In C90 wird hier dem Compiler lediglich gesagt, dass es da zwei Funktionen gibt, mit den Namen function und function_2. Welche Parameter die bekommen ist aber offen. Möchtest Du dem Compiler mitteilen, dass die Funktionen keine Parameter bekommen, musst Du ein void in die Klammern schreiben:
void function(void); void function_2(void);
In C++ ist das void überflüssig. Man hielt es beim Design von C++ für eine ziemlich dämliche Idee, die Angabe über Parameter offen zu lassen. Dementsprechend verhält sich eine leere Klammer in C++ genauso wie eine in C mit void drin. In C++ ist das void aber auch nicht falsch oder schädlich. Aus C-Kompatibilitätsgründen ist es in C++ immer noch erlaubt. In reinem C++ Code solltest du void an dieser Stelle nicht verwenden, da das einfach unüblich ist.
Versuch's also mal mit void in der Klammer.
-
Danke an alle für die Hilfe, jetzt funktioniert es, hier nochmal alle Programme vielleicht kann wer anderes damit auch noch was Anfangen. Ich hab bei wikipedia auch noch 2 interessante Links gefunden:
http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B
http://en.wikipedia.org/wiki/Name_manglingDie C++ Version:
main.cpp
#include <iostream> #include "my_header.h" using namespace std; int main(int argc, char* argv[]) { check_if_file_exists (); system("PAUSE"); return 0; }
my_header.h
#ifndef my_header #define my_header /*/ __cplusplus wird automatisch vom Compiler definiert, wenn ein C++ Compiler verwendet wird (Ist im C++ Standart so festgelegt) /*/ #ifdef __cplusplus // Wenn kein C++ Compiler verwendet wird, dann wird void check_if_file_exists(); ganz normal aufgerufen extern "C" { // Wenn ein C++ Compiler verwendet wird dann wird die Funktion check_if_file_exists(); // mit den C Symbolnamen Compiliert http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B // Weiteres Stichwort: "name mangling" http://en.wikipedia.org/wiki/Name_mangling #endif void check_if_file_exists(); #ifdef __cplusplus // Falls ein C++ Compiler verwendet wurde dann wird hier die Klammer vom exter "C" Befehl geschlossen. } #endif #endif
my_functions.c
#include "my_header.h" #include <iostream> #include <fstream> void check_if_file_exists() { std::ifstream file ("test.txt"); if ( file == NULL ) { std::cout<<"Die Datei test.txt existiert nicht\n"<<std::endl; } else { std::cout<<"test.txt existiert"<<std::endl; } }
Und jetzt die C Version
main.c
#include <stdio.h> #include "my_header.h" int main() { check_if_file_exists(); system("PAUSE"); return 0; }
my_header.h
#ifndef my_header #define my_header #ifdef __cplusplus // Wenn kein C++ Compiler verwendet wird, dann wird void check_if_file_exists(); ganz normal aufgerufen extern "C" { // Wenn ein C++ Compiler verwendet wird dann wird die Funktion check_if_file_exists(); // mit den C Symbolnamen Compiliert http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B // Weiteres Stichwort: "name mangling" http://en.wikipedia.org/wiki/Name_mangling #endif void check_if_file_exists(void); // Wenn aus C eine C++ Funktion aufgerufen werden soll, // und die C++ Funktion keine Parameter erwartet dann muss // der Übergabeparameter void sein, das void muss man nur hier // in my_header.h schreiben #ifdef __cplusplus // Falls ein C++ Compiler verwendet wurde dann wird hier die Klammer vom exter "C" Befehl geschlossen. } #endif #endif
my_functions.cpp
#include "my_header.h" #include <iostream> #include <fstream> void check_if_file_exists() { std::ifstream file ("test.txt"); if ( file == NULL ) { std::cout<<"Die Datei test.txt existiert nicht\n"<<std::endl; } else { std::cout<<"test.txt existiert"<<std::endl; } }
-
#include <stdio.h> #include "my_header.h" int main() { check_if_file_exists(); system("PAUSE"); return 0; }
Schöner:
#include <cstdio>//Benutze die C++-Version dieses Headers #include "my_header.h" int main() { check_if_file_exists(); for(;;);//return-Statement eig. unnötig, es wird Standardmäßig 0 zurückgegeben (Achtung, nur bei main()!) }//system("pause"); ist unportabler Blödsinn. Nimm lieber eine Endlosschleife
Edit: Und brav auf Formattierung achten!
-
Wieso gibt es denn jetzt 2mal eine my_header.h-Datei (Einmal im Abschnitt "C++-Version" und einmal im Abschnitt "C-Version")? Kann das nicht jedes mal dieselbe sein? Die Headerdatei definiert eine C-Schnittstelle. Auf welcher Seite welche Sprache verwendet wird, ist dann ja eigentlich egal, sofern man dort den __cplusplus-Trick eingebaut hat.
Dein IncludeGuard besteht wieder aus Kleinbuchstaben.
-
Hacker schrieb:
//system("pause"); ist unportabler Blödsinn. Nimm lieber eine Endlosschleife
Super Alternative
-
@Hacker: Du hast echt ein komisches Verständnis von Schönheit. Die CPU-Resourcen-verschwendende Tu-Gar-Nichts-Schleife geht ja mal gar nicht!
-
Hacker schrieb:
// Nimm lieber eine Endlosschleife
Das ist undefinierter Blödsinn.
-
Gut, Vorschlag:
std::cin.get();
-
Immer noch nicht gut. Wir haben hier eine FAQ, falls du es noch nicht wusstest.
-
Und was spricht gegen system("pause") wenn er auf seinem Windows-Rechner spielt?
Bezweifle dass seine Spielereien jemals ernsthafte Software werden, die er portieren möchte.
-
Ethon__ schrieb:
Und was spricht gegen system("pause") wenn er auf seinem Windows-Rechner spielt?
Bezweifle dass seine Spielereien jemals ernsthafte Software werden, die er portieren möchte.@SeppJ: Ja, ich weiß dass es hier eine FAQ gibt.
Da steht aber auch nichts großartig anderes drinnen.
-
Hacker schrieb:
@SeppJ: Ja, ich weiß dass es hier eine FAQ gibt.
Da steht aber auch nichts großartig anderes drinnen.Und ob da was anderes drinsteht. Da steht nämlich kein einziger deiner Unsinnsvorschläge.
-
void wait () { std::cin.clear(); std::cin.ignore(cin.rdbuf()->in_avail()); std::cin.get(); }
Diese Funktion verfeinert nur, was ich mit std::cin.get() bereits vorschlug. Und ist nebenbei die erste vorgeschlagene Alternative.