Funktionspointer in C

Hi.

Nein, das geht nicht. Natürlich kannst du alles "weg-casten" was den Compiler stört, aber was bringt dir das? Du kannst dann zwar die Adresse aller möglichen Funktionen speichern, aber du kannst sie ja nicht anwenden, da der Compiler wissen muss wieviel Parameter die Funktion hat und welchen Typ die Parameter und der Rückgabetyp hat. In Abhängigkeit davon muß ja Speicher auf dem Stack für die Übergabe der Argumente und Rückgabe des Funktionsergebnisses reserviert werden.

Gruß
 
Hi.

Danke für die schnelle Antwort, leider ist es zwar nicht das was ich mir erhofft habe, aber die Antwort ist natürlich vollkommend logisch !

Die Sache ist die das ich in Strukturen Funktionspointer speichern muss und ich vermeiden wollte extra für jede Funktion zusätzlich zu der Deklaration in der Headerdatei auch noch einen weitere Deklaration für den Typ des Pointers auf diese Funktion zu schreiben.
 
monger hat gesagt.:
DOCH, das geht eben SCHON!
Beispiel:

Code:
/* ptr_func1.c */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
   int (*ptr) (const char*, ...);
   ptr=printf;
   (*ptr)("Hallo Welt\n");
   return EXIT_SUCCESS;
}
Natürlich geht das für dein Beispiel. Das ist auch nicht verwunderlich, denn die Signatur von printf stimmt ja auch 100%ig mit der Signatur der Funktion überein auf die ptr zeigt. Es soll ja aber für ganz verschiedene Funktionen funktionieren - dein Beispiel funktioniert allerdings nur für Funktionen die eine ganz bestimmte Signatur haben.

Gruß
 
Hmmm, vielleicht geht's doch. Hier mal eine theoretische Überlegung:

Man könnte eine Funktion mit variabler Parameterzahl schreiben in der Art:

Code:
void CallFunction(void * func, void * retval, ...)
{...}
func wäre dann der Zeiger auf die Funktion, an retval kommt der Rückgabewert, danach kämen die Parameter. In dieser Funktion könnte man die Parameter mir Assembler auf den Stack schieben und den Programmzeiger auf die Adresse der Funktion setzen. Wenn der Rücksprung von der Funktion erfolgt ist, kann man den Rückgabewert aus dem entsprechenden Register an die Speicherstelle schreiben, die durch retval angegeben wurde.

Wie gesagt, es ist eine rein theoretische Überlegung. Da mir ein solches Vorhaben ziemlich exotisch (wenn nicht sogar sinnfrei :)) erscheint, habe ich sowas noch nie ausprobiert. Eure Meinung zur Machbarkeit würde mich interessieren.
 
jokey2 hat gesagt.:
Code:
void CallFunction(void * func, void * retval, ...)
{...}
func wäre dann der Zeiger auf die Funktion, an retval kommt der Rückgabewert, danach kämen die Parameter. In dieser Funktion könnte man die Parameter mir Assembler auf den Stack schieben und den Programmzeiger auf die Adresse der Funktion setzen. Wenn der Rücksprung von der Funktion erfolgt ist, kann man den Rückgabewert aus dem entsprechenden Register an die Speicherstelle schreiben, die durch retval angegeben wurde.
Da gibt es aber ein weiteres Problem: was für eine Calling Convention wird denn von der Funktion verwendet? Gut, nehmen wir mal an, wir haben es mit nur einer einzigen Calling Convention zu tun, sonst wird es zu haarig.

Wenn ich jetzt einen Funktionspointer (void*) an eine Funktion übergebe, welche die Funktion CallFunction benutzen soll, stellt sich dann die Frage wie der Aufruf der CallFunction Funktion aussehen muß. Ich muß eben dennoch an der Stelle wissen welche Parameter und welchen Rückgabetyp die Funktion besitzt. Ich kann ja nicht einfach irgendwelche Parameter bzw. irgendeinen Rückgabetyp verwenden. Dann kann ich doch aber lieber gleich den void-Pointer in den konkreten Funktionspointer-Typ casten und spare mir die CallFunction Funktion.
jokey2 hat gesagt.:
Wie gesagt, es ist eine rein theoretische Überlegung. Da mir ein solches Vorhaben ziemlich exotisch (wenn nicht sogar sinnfrei :)) erscheint, habe ich sowas noch nie ausprobiert. Eure Meinung zur Machbarkeit würde mich interessieren.
Ich denke das ist (mit etwas Aufwand) schon irgendwie machbar. Allerdings finde ich es auch nicht unbedingt sinnvoll.

Gruß
 
Es geht ja auch nur um eine Gedankenspielerei. Völlig sinnfrei :)

Ich meine ja auch nicht, daß die Zielfunktion in C-Manier aufgerufen wird, sondern daß eigentlich alles in meiner Beispielfunktion in Assembler implementiert wird, also auch der Funktionsaufruf. Die Zielfunktion wird also per Assembler-'call' mit Funktionsadresse als Sprungziel aufgerufen. Deshalb werden ja auch die Parameter mittels 'push' auf den Stack geschoben, wo sie von der angesprungenen Funktion gelesen werden können. Im Prinzip soll der C-Aufrufmechanismus nachgebildet werden, um die Typüberprüfung des Compilers zu umgehen.
Was die Aufrufkonvention angeht, gebe ich Dir natürlich recht, man muß wissen, welche von der angesprungenen Funktion verwendet wird. Das ist aber solange kein Problem, wie man die Zielfunktionen selber kompiliert.
 
Zurück