ich bin etwas neu in C++. In C bin ich eigentlich recht flüssig. Nun zu meiner Frage.
Kann ich in C++ ohne weiteres Pointer an C übergeben oder muss diese Funktion, Variable usw... bestimmte Bedingungen erfüllen?
Was ich bisher zu wissen glaube:
Klassen können logischerweise nicht direkt übergeben werden. Als void* ist das aber möglich. Hier ist aber zu beachten, dass bestimmte Funktionen wie memcpy nur bei POD-Klassen funktionieren.
Als static "C" deklarierte Funktionen können direkt im C-Code verwendet werden. Einfache Variablen und Funktionen können also mit etwas Aufwand an C übergeben werden.
Ich habe widersprüchliche Dinge gelesen über das Übergeben von Klassenmember-Pointern. Deshalb bitte ich hier um Klarstellung. Kann ich nun einfach einen Pointer auf einen Klassenmember übergeben oder geht das nur unter bestimmten Vorraussetzungen? Wenn ja welche Voraussetzungen muss ich beachten?
Deshalb bitte ich hier um Klarstellung. Kann ich
nun einfach einen Pointer auf einen Klassenmember übergeben oder geht
das nur unter bestimmten Vorraussetzungen?
Das Klassenmember muss ein Datentyp sein, mit dem C etwas anfangen kann.
Ja. Du kannst auch einen Zeiger auf eine Klasse z.B. nach void* umcasten, an C übergeben, dann aus C wieder zurück bekommen, zurück auf den Klassentyp casten, und normal weiter verwenden. Das wird oft gemacht bei Callbacks aus C-Code mit dem typischen "void* user_data" -Argument.
Klassen können logischerweise nicht direkt übergeben werden. Als void*
ist das aber möglich. Hier ist aber zu beachten, dass bestimmte
Funktionen wie memcpy nur bei POD-Klassen funktionieren.
Da C keine Klassen kennt, kannst du in C mit einem pointer auf eine C++-Klasse nur sehr wenig anfangen, egal, wohin du den auch castest. Eine C++-Klasse über einen pointer in C zu kopieren, wäre wohl ein nur in der allergrößten Not anzuwendender Hack.
Ich habe widersprüchliche Dinge gelesen über das Übergeben von
Klassenmember-Pointern. Deshalb bitte ich hier um Klarstellung. Kann ich
nun einfach einen Pointer auf einen Klassenmember übergeben oder geht
das nur unter bestimmten Vorraussetzungen? Wenn ja welche
Voraussetzungen muss ich beachten?
Neben dem schon gesagten muß man dabei, wie überall beim hantieren mit Pointern, auf deren Gültigkeit bzw. die Lebensdauer der Instanz dazu achten.
Können diese Funktionen innerhalb des C-Codes dann auch
aufgerufen/verwendet werden
Nein, du kannst keine Member-Funktionen aus C-Code heraus direkt aufrufen, egal ob virtual oder nicht. Du kannst aber einfach eine globale Funktion (mit extern "C") erstellen und von dort die Member-Funktion aufrufen.
Von statischen Member-Funktionen kannst du aber einen Funktionszeiger erstellen, nach C übergeben und dort aufrufen. Direkt geht es aber auch nicht.
Da C keine Klassen kennt, kannst du in C mit einem pointer auf eine
C++-Klasse nur sehr wenig anfangen, egal, wohin du den auch castest.
Eine C++-Klasse über einen pointer in C zu kopieren, wäre wohl ein nur
in der allergrößten Not anzuwendender Hack.
Nö, das ist eigentlich was ganz normales. Man kann sich den Zeiger merken, d.h. er wird in einer C++-Funktion erzeugt, auf der C-Seite bekommt man den Zeiger und kann ihn dann später nutzen, um damit eine andere C++-Funktion aufzurufen.
Können diese Funktionen innerhalb des C-Codes dann auch
aufgerufen/verwendet werden
Nein, du kannst keine Member-Funktionen aus C-Code heraus direkt
aufrufen, egal ob virtual oder nicht. Du kannst aber einfach eine
globale Funktion (mit extern "C") erstellen und von dort die
Member-Funktion aufrufen.
Und dann das Objekt eben per void* übergeben.
Von statischen Member-Funktionen kannst du aber einen Funktionszeiger
erstellen, nach C übergeben und dort aufrufen. Direkt geht es aber auch
nicht.
Das funktioniert zwar bei allen mir bekannten Compilern, ist aber offiziell eigentlich nicht erlaubt. Von C aus dürfen nur Funktionen aufgerufen werden, die als extern "C" definiert sind, und das ist bei statischen Memberfunktionen nicht möglich.
Von C aus dürfen nur Funktionen
aufgerufen werden, die als extern "C" definiert sind
Wie kommst Du auf diese Idee?
Direkt (ohne Funktionspointer) lassen sie sich wegen ihrer Linkersignatur nicht anders verwenden, aber warum sollte die Verwendung statischer C++-Member via Funktionspointer "illegal" sein?
Das halte ich für ziemlich ausgeschlossen, denn dann wäre schlagartig eine irrwitzig große Menge von Code nicht mehr verwendbar.
Von C aus dürfen nur Funktionen
aufgerufen werden, die als extern "C" definiert sind
Wie kommst Du auf diese Idee?
Das steht so im C++-Standard.
Direkt (ohne Funktionspointer) lassen sie sich wegen ihrer
Linkersignatur nicht anders verwenden, aber warum sollte die Verwendung
statischer C++-Member via Funktionspointer "illegal" sein?
Weil extern "C" sich nicht nur auf die Signatur bezieht, sondern auf alle Aspekte eines Funktionsaufrufs, also auch Aufrufkonventionen, z.B. wie Parameter übergeben werden. Ob so ein Aufruf ohne extern "C" trotzdem funktioniert, hängt also letztlich davon ab, ob das vom Compiler umgesetzte ABI für C und für C++ im Bezug auf Funktionaufrufe gleich ist.
Das halte ich für ziemlich ausgeschlossen, denn dann wäre schlagartig
eine irrwitzig große Menge von Code nicht mehr verwendbar.
Das ist nicht schlagartig so, sondern war schon immer so.
Da C keine Klassen kennt, kannst du in C mit einem pointer auf eine
C++-Klasse nur sehr wenig anfangen, egal, wohin du den auch castest.
Eine C++-Klasse über einen pointer in C zu kopieren, wäre wohl ein nur
in der allergrößten Not anzuwendender Hack.
Nö, das ist eigentlich was ganz normales. Man kann sich den Zeiger
merken, d.h. er wird in einer C++-Funktion erzeugt, auf der C-Seite
bekommt man den Zeiger und kann ihn dann später nutzen, um damit eine
andere C++-Funktion aufzurufen.
Mit einem pointer auf eine C++-Klasse willst du aus C eine andere C++-Funktion aufrufen? Oder meinst du, du gibst den unverändert an C++ zurück, und kannst den dann da ganz normal nutzen?
Nö, das ist eigentlich was ganz normales. Man kann sich den Zeiger
merken, d.h. er wird in einer C++-Funktion erzeugt, auf der C-Seite
bekommt man den Zeiger und kann ihn dann später nutzen, um damit eine
andere C++-Funktion aufzurufen.
Mit einem pointer auf eine C++-Klasse willst du aus C eine andere
C++-Funktion aufrufen? Oder meinst du, du gibst den unverändert an C++
zurück, und kannst den dann da ganz normal nutzen?
Letzteres wäre völlig normal.
Ja, das meinte ich. Ich schrieb ja, dass es auf der C-Seite nur darum geht, sich den Zeiger zu merken, um ihn später wieder an die C++-Seite übergeben zu können.
Ja, das meinte ich. Ich schrieb ja, dass es auf der C-Seite nur darum
geht, sich den Zeiger zu merken, um ihn später wieder an die C++-Seite
übergeben zu können.
Und das meinte ich damit, daß man auf der C-Seite damit nicht viel anfangen kann, ausser den wieder zurückzugeben.
Ja, das meinte ich. Ich schrieb ja, dass es auf der C-Seite nur darum
geht, sich den Zeiger zu merken, um ihn später wieder an die C++-Seite
übergeben zu können.
Und das meinte ich damit, daß man auf der C-Seite damit nicht viel
anfangen kann, ausser den wieder zurückzugeben.
Ja, aber du schriebst was von Hacks, die man nur in größter Not anwenden sollte, wobei mir nicht klar ist, was du mit "Eine C++-Klasse über einen pointer in C zu kopieren" meintest. Möglicherweise hast du dich da auf was anderes bezogen und ich habe es missverstanden.
"Some of the properties associated with an entity with language linkage are specific to each implementation and are not described here. For example, a particular language linkage might be associated with a particular form of representing names of objects and functions with external linkage, or with a particular calling convention, etc."
Mit anderen Worten: name-mangling ist nicht das einzige, was da hinein spielt. Mit extern "C" kümmert sich der Compiler um alle Unterschiede, die es bei Funktionsaufrufen geben könnte, ohne funktioniert's halt nur, wenn die calling conventions übereinstimmen.
Übrigens sind ein Zeiger auf eine Funktion, die extern "C" ist und ein Zeiger auf eine Funktion ohne extern "C" auch grunsätzlich verschiedene Typen. ("Two function types with different language linkages are distinct types even if they are otherwise identical.")
Ja, aber du schriebst was von Hacks, die man nur in größter Not anwenden
sollte, wobei mir nicht klar ist, was du mit "Eine C++-Klasse über einen
pointer in C zu kopieren" meintest.
Klassen können logischerweise nicht direkt übergeben werden. Als void*
ist das aber möglich. Hier ist aber zu beachten, dass bestimmte
Funktionen wie memcpy nur bei POD-Klassen funktionieren.
Noch ein Zitat aus dem genannten Draft:
"Because the language linkage is part of a function type, when indirecting through a pointer to C function, the function to which the resulting lvalue refers is considered a C function."
Ich habe widersprüchliche Dinge gelesen über das Übergeben von
Klassenmember-Pointern. Deshalb bitte ich hier um Klarstellung. Kann ich
nun einfach einen Pointer auf einen Klassenmember übergeben oder geht
das nur unter bestimmten Vorraussetzungen? Wenn ja welche
Voraussetzungen muss ich beachten?
Wie oben genannt, für static gelinkte Klassenfunktionen kein Problem, mit extern "C"-Wrapper fürs Name-Mangling und Konventionen (falls nötig).
Bei normalen Member-Funktionen wird's glaube komplizierter. Im einfachsten Fall kannste es wie bei der WINAPI-Programmierung üblich, das Objekt als void* reingeben wo aber noch der Offset zur Memberfunktion mit drauf müsste.
In C++ kannste sowas machen wie:
1
#include <iostream>
2
3
struct Foo
4
{
5
int a = 123;
6
7
int meineTolleFunc() const { return a; }
8
};
9
10
int main(int argc, char** argv)
11
{
12
Foo a;
13
14
Foo* b = &a;
15
int (Foo::*fnCallback)() const = &Foo::meineTolleFunc;
16
17
// zusammensetzung obj + memfn-cb:
18
std::cout << (b->*fnCallback)() << std::endl;
19
return 0;
20
}
Könnte vielleicht nen Versuch wert sein, musst halt immer das Objekt und die zugehörige Klassen-relative Callback mit durchschleifen, um die aufrufen zu können. Ob du das Zeug dann aus reinem C aus ohne C++-Wrapper aufrufen kannst, weiß ich nicht.