2016-10-03 3 views
0

Angenommen, ich eine Druckfunktion haben, die einen void * als Argument:Wie übergebe ich eine Funktion mit einem festen Parameter an eine andere Methode in C?

Print(void *instance) 

Wie kann ich das Mitglied einer Struktur dieser Methode setzen?

struct Foo 
{ 
    void(*Print)(); //this does not match to Print above! 
    //void(*Print)(void* Instance); //This would but I cannot change this 
} 

Wie hätte ich diese Methode ändern:

void Init() 
{ 
    struct Foo* k = malloc(sizeof(Foo)); 

    Foo->Print = &Print(k); //does not work?! 
    //Foo->Pring = &Print;  //would work if types were the same 
} 

Ich möchte mit einem festen Argument einen Funktionszeiger innerhalb einer Struktur setzen.

Grundsätzlich ist dies eine Möglichkeit, objektorientierten Code in ANSI-C zu implementieren. Das Source-Projekt ist dies: Object Orientation in C?!

Das über das Ändern dieses Stückes C-Code wäre:

String* r = New_String("Hello"); 
r->Free(r); //this works 
r->Free(); //this is how it should be! 

So, dass die Instanz nicht auf die Methoden themselfes weitergegeben werden muss.

Zusammengefasst: Ziel ist, die Foo-Instanz in Print zu bekommen, der wie Foo-> Print();

+0

Wie planen Sie es nennen? Versuchen Sie, einen Zeiger auf eine Funktion zu verwenden, die einen Parameter akzeptiert, und ihn dann mit dem Parameter aufgerufen zu haben, der tatsächlich für Sie ausgefüllt wurde, wenn Sie den Funktionszeiger zugewiesen haben? Das ist nicht möglich ... Sie müssten einen anderen Ansatz wählen. Jeder Aufruf müsste den Parameter explizit übergeben. – Dmitri

+0

Das wäre genau das Problem. Andere Sprachen unterstützen es so: Foo.Print =() => Print (k); Vielleicht kann man für jeden Anruf manuell k zum Stack hinzufügen? –

+1

Es scheint, dass Sie Pseudo-C++ - Code gepostet haben und dasselbe in C tun wollen. Das Problem ist, dass der Code einfach wie ungültiger C-Code erscheint. Schlagen Sie Ihren Kommentar in den Beitrag ein und versuchen Sie, Ihr Ziel besser zu klären, vielleicht fügen Sie Beispielanrufe hinzu. – chux

Antwort

0

mit:

Foo->Print = &Print(k); 

Sie zuweisen einen Funktionszeiger und Sie "calling" die Funktion mit einem Parameter sind. Das ist falsch. Was Sie tun können ist:

Foo->Print = Print; 
Foo->Print = (void(*)())Print; // if compiler complains, use a cast 

Da Print eine Funktion ist, wird der Compiler seine Adresse zu verwenden, wenn es um das Funktionszeigerfeld der Struktur zuweisen. Aber weil Ihre Print-Funktion mit dem Feld Print nicht kompatibel ist, müssen Sie eine Umwandlung verwenden, um den Compiler stumm zu schalten. Ihre Print Funktion wird zu einer "Funktion, die eine beliebige Anzahl von Parametern annehmen kann" vergeben. Das Casting ist hier sicher, solange Sie es mit mindestens einem Parameter aufrufen. Führe dieses Casting nur aus, wenn du weißt, was du machst, oder ein undefiniertes Verhalten folgt.

Sobald der Funktionszeiger zugeordnet ist, können Sie nun mit Ihrem Parameter nennen:

Foo->Print(k); 
+0

Schlechtes Ding ist k sollte nicht danach verwendet werden. Ich habe meine Frage dazu geklärt. Verrückte Dinge sind auch erlaubt. Ziel ist es, irgendwie die Foo-Referenz in Print zu bekommen. Stack Manipulation, Assembler, alles geht! –

+0

Wie wird das Hinzufügen eines Members 'k' wie' Foo-> k = k; 'und so' Foo-> Print (Foo-> k); '? –

+0

So funktioniert es jetzt. Noch besser: Foo-> Drucken (Foo) da brauchst du nur die Adresse. Aber ich brauche Foo-> Print(); –

Verwandte Themen