PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : function pointer, wird jemand daraus schlau?


rotalever
2007-08-01, 18:12:31
cache.cpp: In constructor »fonching::cache::cache(int)«:
cache.cpp:34: Fehler:
»FT_Error (fonching::cache::*)(FTC_FaceIDRec_*, FT_LibraryRec_*, void*, FT_FaceRec_**)«
kann nicht nach
»FT_Error (*)(FTC_FaceIDRec_*, FT_LibraryRec_*, void*, FT_FaceRec_**)«
für Argument »5«
nach
»FT_Error FTC_Manager_New(FT_LibraryRec_*, FT_UInt, FT_UInt, FT_ULong, FT_Error (*)(FTC_FaceIDRec_*, FT_LibraryRec_*, void*, FT_FaceRec_**), void*, FTC_ManagerRec_**)« umgewandelt werden

Dies ist die Ausgabe meines GCC compilers. Die Klasse cache ist ein Singleton in deren Konstruktor ich einige Funktionen aufrufe:

FT_Error (cache::*ptr)( FTC_FaceID, FT_Library, FT_Pointer, FT_Face* ) = NULL;
ptr = &cache::font_requester;
FT_Init_FreeType( &library );
FTC_Manager_New( library, 0, 0, max_memory, ptr, NULL, &cachemanager );
....

Der Fehler kommt hier in der letzten Zeile.
Die Funktion, auf die gepointet wird sieht so aus:

FT_Error cache::font_requester( FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face* aface )
{
FT_New_Face( library,"kochi-mincho-subst.ttf", 0, aface );
return 0;
}

Wenn ich das ganze ohne Klassen realisiere, also einfach die Funktion nehme und dann FTC_Manager_New(...) mit Pointer zu einer Funktion (&font_requester) aufrufe, spuckt er keine Fehler aus und es läuft alles.

Packe ich das ganze und die Funktion aber in diese Klasse läuft es nicht mehr. Woher könnte so etwas kommen? Bzw. was habe ich darunter zu verstehen wenn der Compiler im übertragenen Sinne sagt: "'A' kann nicht nach 'A' für Argument 'n' nach 'Bla' umgewandelt werden"?

Face Requester Definition: http://www.freetype.org/freetype2/docs/reference/ft2-cache_subsystem.html#FTC_Face_Requester

Neomi
2007-08-01, 18:27:26
Wenn ich das ganze ohne Klassen realisiere, also einfach die Funktion nehme und dann FTC_Manager_New(...) mit Pointer zu einer Funktion (&font_requester) aufrufe, spuckt er keine Fehler aus und es läuft alles.

Scheint so, als hättest du den impliziten this-Pointer vergessen. Du brauchst eine statische Methode.

rotalever
2007-08-01, 18:32:44
Scheint so, als hättest du den impliziten this-Pointer vergessen. Du brauchst eine statische Methode.
Verstehe ich jetzt nicht so ganz, was Du mit dem this-Pointer meinst. An welcher Stelle benötige ich den denn?

Als static hatte ich die Funktion vorher schon mal deklariert, der Fehler ist dann zwar weg, aber der sagt dann dafür:

cache.cpp:105: Fehler: Elementfunktion »static FT_Error fonching::cache::font_requester(FTC_FaceIDRec_*, FT_LibraryRec_*, void*, FT_FaceRec_**)« kann nicht deklariert werden, statische Bindung zu haben

rotalever
2007-08-01, 19:35:31
Ich weiß zwar immer noch nicht, was mit dem this gemeint war aber dass die Funktion static sein muss ist natürlich vollkommen richtig. Mein Fehler war nur, dass ich sowohl im header "static ..." also auch in der Implementierung "static..." geschrieben habe und das dann der Fehler war... Jetzt kompiliert es zumindest ohne Probleme.

Neomi
2007-08-01, 20:36:01
Verstehe ich jetzt nicht so ganz, was Du mit dem this-Pointer meinst. An welcher Stelle benötige ich den denn?

Ich habe gerade ernsthaft erstmal gerätselt, was für ein Problem du mit dem this-Pointer haben könntest. Darauf, daß du ihn nicht kennst, bin ich gerade erst gekommen, das kam mir wohl zu unwahrscheinlich vor.

Wenn du verschiedene Objekte einer Klasse hast und über ein Objekt eine Methode aufrufst, dann soll die Methode auch mit den Daten des richtigen Objektes arbeiten. Nicht mit denen von einem beliebigen Objekt und nicht mit den Daten an einer zufälligen Adresse im Speicher. Zur Compilezeit weiß die Methode zwar, zu welcher Klasse sie gehört, aber nicht zu welchem Objekt. Deshalb ist ein Pointer nötig, der bei C++ für Instanzmethoden implizit mitgeliefert wird und eben "this" heißt. Kleines Codebeispiel:

class Blablub
{
private:
int bla;
int blub;

public:
void SetValues(int newbla, int newblub)
{
bla = newbla;
blub = newblub;
}
};

Blablub b1, b2;

b1.SetValues(1, 2);
b2.SetValues(3, 4);

Implizit wird das vom Compiler so erweitert, damit immer das richtige Objekt verwendet wird:

class Blablub
{
private:
int bla;
int blub;

public:
void SetValues(int newbla, int newblub, Blablub *this)
{
this->bla = newbla;
this->blub = newblub;
}
};

Blablub b1, b2;

b1.SetValues(1, 2, &b1);
b2.SetValues(3, 4, &b2);

Genau durch diesen impliziten Parameter stimmte die Signatur deiner Methode nicht mit der geforderten Signatur für die Callback-Funktion überein. Statische Methoden haben keinen this-Pointer, weshalb sie dann auch nur auf statische Elemente (eben Klassenelemente) zugreifen können. Explizit ansprechen kann man den this-Pointer natürlich auch, in manchen Situationen geht es nicht anders.

Ectoplasma
2007-08-01, 23:04:05
Kleine Anmerkung. Der This Pointer ist implizit immer vorne.


class Blablub
{
private:
int bla;
int blub;

public:
void SetValues(Blablub *this, int newbla, int newblub)
{
this->bla = newbla;
this->blub = newblub;
}
};



Denn auch eine C++ Methode kann mit dem Epsilon Operator (...) eine variable Parameterliste besitzen. Mit anderen Worten. Die Anzahl der Parameter ist nicht bekannt, daher ist This immer vorne.

Danke für Ihre Aufmerksamkeit.

rotalever
2007-08-01, 23:22:38
Also was ein this pointer ist wusste ich nur nicht was Du mit einem <implizierten> meinst.:smile:

Habe ich das jetzt richtig verstanden, dass ich da keinen this pointer dazugeben kann, zu meiner statischen Funktion, da sonst das Callback interface nicht mehr funktioniert?

Wenn es so ist, macht das aber nichts weiter, denn ersten wäre es ja ein Singleton und es gibt sowieso nur eine Instanz und zweites, und das ist wohl der bessere Weg, bietet mir die Methode, der ich den Funktions-pointer übergebe die Möglichkeit noch ein paar Daten mitzuliefern. Das was ich im Beispiel als NULL gelassen habe könnte ich auch mit "this" füllen und hätte dann dieses this in der callback Funktion zu Verfügung.

Danke für die Infos und gute Nacht;)