Warum wird C++11 keine Unterstützung für die Deklaration extern "C" auf eine statische member-Funktion?
Zur Verfügung gestellt, dass ich eine C-Bibliothek, die eine Funktion deklariert als void g(void (*callback)());
Der folgende code ist eine elegante und dennoch rechtswidrig ist:
struct A
{
//error C2159: more than one storage class specified (VC++ Nov 2012 CTP)
static extern "C" void callback()
{}
};
g(A::callback);
Warum C++11 nicht unterstützen diese?
- Haben Sie versucht, ohne die
extern "C"
? - Wenn ohne extern "C", der name der Funktion wird entstellt und die Verbindung schlägt fehl.
- was link-Fehler? es kompiliert auf gcc4.7.2
- Sind Sie sicher, dass die Verknüpfung wird scheitern?
- Wenn
g
erwartet eineextern "C" void (*)()
, danng(&A::callback)
ist illegal, und erfordert einen compiler Diagnose. Viele Compiler nicht, dies durchzusetzen, allerdings (und sind dadurch gebrochen in dieser Hinsicht). - Fehler C2159: mehr als ein Speicher-Klasse angegeben (VC++ Nov 2012 CTP)
- Aber die C-Funktion aufrufen nicht den Rückruf mit Namen, es sieht nur einen Zeiger. So ist der name mangling ist ein nicht-Problem. Versuchen Sie bitte, bevor Sie Fragen.
- Name mangling ist nicht das Problem. Aufrufkonventionen sind. Name mangling ist Teil der Aufruf-Konventionen, aber es ist nicht alle von Ihnen. Ich habe tatsächlich verwendet einen compiler, wo C und C++ verwendet unterschiedliche Aufrufkonventionen (Aufrufer bereinigt den stack in C, angerufene in C++).
- nicht zu sein scheinen eine gute Passform für eine Frage ALSO, die Antwort kann nur erahnt werden.
- Nein, wir haben mehrere Mitglieder des Ausschusses SO und wir haben alle die vor-und postmailings von den Ausschusssitzungen öffentlich verfügbar. folglich gibt es keine Notwendigkeit zu erraten.
- Für den Datensatz, G++ ignoriert Sprache Verknüpfung von Funktions-Typen, aber das ist ein bug. Clang++ auch ignoriert, vermutlich für G++ - Kompatibilität.
- sollte nur Fragen, praktische, vertreten hat, die Fragen auf der Grundlage der tatsächlichen Probleme, denen Sie begegnen. Gesprächige, offene Fragen vermindern die Nutzbarkeit unserer Website und schieben andere Fragen aus der front Seite"
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist ein besonders verwirrendes Thema zu waten in. Let ' s Angriff §7.5 "Verknüpfung Spezifikationen" [dcl.link].
Beachten Sie, dass die Eigenschaft von Sprache, die Verknüpfung gilt für zwei völlig verschiedene Arten von Entitäten: Arten und Namen.
Eine Funktion hat, eine allgemein unsichtbar bit der Informationen, die in Ihrer Art identifiziert, die die ABI-es passt sich an an: C Aufrufkonventionen Pascal, Fortran, könnte angegeben werden, um die stack in unterschiedlicher Weise, so ruft Sie über einen Zeiger muss man wissen, das unsichtbare der Sprache-zu-tag -.
Den Namen eine variable oder eine Funktion aus einer anderen Sprache zugegriffen werden kann syntaktisch durch C++ - oder aus der anderen Sprache bezieht sich auf eine C++ - Deklaration. Aber nicht jede Sprache können match mit C++'s naming scheme und OO-Modell. Also Schnittstellen, die in diesem Schema nicht enthalten Klassen.
Weil diese Dinge getrennt verwaltet werden, ist es möglich, etwas zu haben, mit Verschieden Gestänge in seiner Art (calling conventions) und seinen Namen (linker-symbol).
Den
extern "C" {}
wirkt sich auf alle Funktions-Deklarationen, einschließlich Zeiger und Referenzen, außer member-Funktionen. Da eine Funktion nur definiert werden, die in einem namespace oder als Mitglied von C-Funktionen kann nur definiert werden im namespace-Gültigkeitsbereich.Die Norm gibt hier ein Beispiel:
Können Sie emulieren das Verhalten, das Sie wollen mit einer
typedef
, obwohl. Von einem anderen Beispiel die in §7.5/4,Kombiniert man diese Beispiele mit Ihnen, können Sie haben
In der Praxis selten einen Unterschied macht. C und C++ kompatible Aufrufkonventionen auf den meisten Plattformen (siehe Jonathan Wakely ' s Kommentare auf dieser Seite, für die Ausnahmen), solange Sie nicht versuchen, pass oder return ein nicht-POD C++ - Klasse geben. Dies ist eine weniger-umgesetzt feature von C++, aufgrund der verwirrenden überlastung der Begriffe und begrifflichen Unterscheidungen reicht von subtil bis akademisch.
extern "C" typedef void x(); struct A { static x f; };
. Macht die Skillung definieren Sie das Verhalten dieser? ich bin derzeit auf Eile und kann nicht schauen.mf3
Sprache C-Verknüpfung. Beachten Sie, dass es die parametermf2
hat die Sprache C Verknüpfung, nicht der Typ, dermf2
selbst. d.h. eine statische member-Funktion einer Klasse in einerextern "C"
- block noch der C++ - Sprache-Verknüpfung.f
istextern "C++"
so wie es erklärt war normal.extern "C"
innerhalb der Klasse (ich kann erklären dieextern "C"
Funktion außerhalb der Klasse und erklären Sie, ein Freund zu sein, aber ich kann es nicht ohne die externe (und sichtbar) decl.)Erste, der Deklaration der Funktion ist legal. Die
extern "C"
,allerdings wird ignoriert, für die Schüler, so dass, wenn
g
erwartet eineextern "C" void (*)()
Sie nicht bestehen können, escallback
.Als um das warum, ich vermute, dass ursprünglich, war es vor allem
eine Frage der Orthogonalität: es macht keinen Sinn für eine Klasse
Mitglied Funktion
extern "C"
im Allgemeinen, und Orthogonalität(oder einfach als niemand den Fall von static-member) bedeutet
dies gilt sowohl für statische member-Funktionen als gut, obwohl
so dass Sie
extern "C"
nützlich gewesen wäre. Heute(z.B. C++11), wäre es problematisch, ändern Sie die Regel,
da könnte es brechen vorhandenen code. IMHO, das ändern würde
akzeptabel, weil die Menge an code, die es brechen würde ist
wahrscheinlich sehr klein, und der Bruch-Ergebnisse in einer compile-Zeit
Fehler—keine änderung in der Laufzeit-Semantik—also leicht
erkannt und behoben werden. Noch, soweit ich weiß, hat sich niemand
ein Vorschlag um dies zu ändern, so dass es nicht geändert.
extern "C"
ist illegal für die Schüler. 7.1.1/6: Die extern-Bezeichner können nur angewandt werden, um die Namen von Variablen und Funktionen. Der externe Planer kann nicht verwendet werden, in der Deklaration der Klasse oder Parameter der Funktion. hat Es schon illegal, da C++98 zu.extern "C"
ist nur zulässig bei namespace-Gültigkeitsbereich. 7.5/4: "Eine linkage-Angabe erfolgen nur im namespace-Gültigkeitsbereich (3.3)" Ihr Zitat aus demselben Absatz wird die Bezugnahme auf, wenn eine Klasse angezeigt wird, innerhalb einerextern "C" { }
block.extern "C" static ...
in einer Klasse, aber anscheinend war ich Irre (oder war der Umgang mit einem compiler-Fehler).extern "C" { }
oder wenn der Typ der Funktion ist definiert durch eine Typdefinition enthält eineextern "C"
. Letzteres ist interessant, weil es erlaubt die Definition einer member-Funktion, die einen Zeiger auf einextern "C"
Funktion.