Hi, 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? Hoffe ihr könnt mir da weiterhelfen. MFG
Aabeku K. schrieb: > 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.
Aabeku K. schrieb: > - Als static "C" deklarierte Funktionen Du meinst 'extern "C"'. ja? Dann stimmt es. Aabeku K. schrieb: > Kann ich > nun einfach einen Pointer auf einen Klassenmember übergeben Ja, das ist kein Problem. Das wird sehr oft so gemacht. Aabeku K. schrieb: > Als void* > ist das aber möglich. 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.
Aabeku K. schrieb: > - 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. Aabeku K. schrieb: > 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. Oliver
Kann ich auch einen Pointer von einer überladenen Funktion oder einer virtuellen Funktion übergeben? Also z.B.:
1 | class example{ |
2 | [...] |
3 | void foo(int data); |
4 | void foo(char name); |
5 | |
6 | virtual void vfoo(int data); |
7 | }; |
Können diese Funktionen innerhalb des C-Codes dann auch aufgerufen/verwendet werden oder geht das wiederum nur im C++-Code?
Aabeku K. schrieb: > 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.
:
Bearbeitet durch User
Oliver S. schrieb: > 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. Niklas G. schrieb: > Aabeku K. schrieb: >> 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.
Rolf M. schrieb: > 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.
Harald K. schrieb: > Rolf M. schrieb: >> 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.
:
Bearbeitet durch User
Rolf M. schrieb: > Oliver S. schrieb: >> 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? Letzteres wäre völlig normal. Oliver
Oliver S. schrieb: >> 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.
Rolf M. schrieb: > 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. Oliver
Oliver S. schrieb: > Rolf M. schrieb: >> 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. Harald K. schrieb: > Rolf M. schrieb: >> Das steht so im C++-Standard. > > Magst Du das präzisieren? Aus Draft N4950: "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.")
:
Bearbeitet durch User
Rolf M. schrieb: > 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. Das bezog sich auf Aabeku K. schrieb: > - 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. Oliver
Ok, dann war es ein Missverständnis, und wir sind uns eigentlich einig.
Rolf M. schrieb: > Ü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. Und wie schreibt man diese verschiedenen Typen hin? LG, Sebastian
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." Sebastian W. schrieb: > Und wie schreibt man diese verschiedenen Typen hin? Beispiel aus dem Draft:
1 | extern "C" typedef void FUNC_c(); |
2 | class C { |
3 | void mf1(FUNC_c*); // the function mf1 and its type have C++ language linkage; |
4 | // the parameter has type “pointer to C function”
|
5 | FUNC_c mf2; // the function mf2 and its type have C++ language linkage |
6 | static FUNC_c* q; // the data member q has C++ language linkage; |
7 | // its type is “pointer to C function”
|
8 | };
|
9 | extern "C" { |
10 | class X { |
11 | void mf(); // the function mf and its type have C++ language linkage |
12 | void mf2(void(*)()); // the function mf2 has C++ language linkage; |
13 | // the parameter has type “pointer to C function”
|
14 | };
|
15 | }
|
Aabeku K. schrieb: > 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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.