error: invalid cast to function type 'void* ()()'



  • Habe vergessen einen Prototyp anzulegen - mal schauen obs funzt.



  • Kode - mal schauen:
    main.cpp:

    MyClass *global_dlg = NULL;
    
    main(){...}
    

    irgendwo kann dieser Dialog im Programm deffiniert werden.
    myclass.h:

    class MyClass: public QDialog
    	{
    		Q_OBJECT
    	public:
    	...
    		struct Entry
    			{
    			int state;
    			bool *value;
    			char *name;
    			QWidget *w;
    			bool *value_w;
    			void *member();
    			};
    	...
    		int register_bool( bool *value, char *name, QWidget *w,  bool *value_w, void *member, char *description = NULL );
    

    O.K. jetzt wird die Funktion aufgerufen, nur die Adresse wird noch falsch benutzt - hängt sich auf - noch ein bischen rumexeperimentieren ...



  • dein Entry[i] ganz oben passt überhauptnicht zu der Struct-definition. irgendwie scheinst du da murks zu machen...



  • So passierts, wenn man Kode zusammenfasst.
    Nennen wir es boolEntry.
    Habe da einige Fehler drin (:6,:13,:16)! Jetzt wird das alles noch umständlicher, da nur static Funktionen gelinkt, bzw. als Laufzeitobjekte zulässig sind:

    class MyClass: public QDialog
        {
            Q_OBJECT
        public:
        ...
            struct boolEntry
                {
                int state;
                bool *value;
                char *name;
                QWidget *w;
                bool *value_w;
                void (*member)(QWidget *w);
                };
        ...
            int register_bool( bool *value, char *name, QWidget *w,  bool *value_w, void(*member)(QWidget *w), char *description = NULL );
    

    Deshalb brauche ich jetzt noch den Zeiger auf das Klassenobject, das dann in dem member gecastet wird und ich somit in dem member auf die Klassenelemente zugreifen kann.
    (Sowas umständliches, da würde man doch am liebsten alles in Assembler programmieren)



  • bastl schrieb:

    So passierts, wenn man Kode zusammenfasst.

    ann mach ich doch mal einen Vorschlag: Gib uns doch bitte einen vollständigen und Code, der auf das wesentliche reduziert ist, den man durch den Compiler jagen kann so dass man nur dein beschriebenes Problem bekommt. Bei den Fetzen die du uns hier ausspuckst blickt man nicht so recht durch, geschweige denn dass man erkennt wo eigentlich dein Problem ist.



  • Der Cast dort oben ist mir sowieso suspekt; es müsste wenn überhaupt (void (*)()) heissen, und auch dies würde keinen Sinn ergeben, da es ja um Memberfunktionen geht. Stattdessen ist dort doch das Casting sowieso überflüssig. Um die Kentnisse nochmals ein wenig aufzufrischen was dieses Thema betrifft, hier ein kleines Beispiel:

    #include <iostream>
    
    using namespace std;
    
    class foo
    {
    public:
        void bar() const
        {
            cout << "TEST" << endl;
        }
    };
    
    int main()
    {
        foo thingy;
        void (foo::*mem_fun_ptr)() const = &foo::bar;
        (thingy.*mem_fun_ptr)();
    
        return 0;
    }
    

    MfG 😉



  • Mit der Beschreibung "recall" sollte die Problemstellung eigentlich voll beschrieben sein.
    Sorry, aber es gibt nicht mehr betroffenen Kode.
    Jedoch heißt dieses Projekt Keda und kann downgeloaded werden.
    Dieses Problem ist dann in der Version 0.1.6 umgesetzt und funktioniert.
    Die Klasse heißt dann Config und das zugehörige Objekt config_dlg; über /Tools/Oscilloscope kann das testwidget eingefügt werden und im Konfigurationsdialog getestet werden.
    ftp://ftp.berlios.de/pub/keda

    Im letzten Kode oben sind immer noch ein paar Fehler, jedoch wird die Problematik sehr gut auf dieser Seite erklärt:
    http://www.goingware.com/tips/member-pointers.html
    Hier müssen die Grenzen von C++ Aufgefürt werden und ich finde dies ist ein sehr schönes Beispiel. Ich habe mich auch schon gewundert, warum der KConfigDialog so kompliziert aufgebaut ist und stoße hier auch an die unzumutbaren Grenzen von C++. Das soll jetzt nicht heißen, daß mit C++ irgendetwas nicht möglich sei,edoch ist die schreibarbeit und der logische Aufwand so aufwendig, zeitraubend und sinnloß, daß ich verstehe, daß hier viele Programmierer zum Assembler (NASM) greifen und assembler Objecte einlinken.
    Vorallem hat C++ volatile und könnte sehr gut direkte Zeiger auf Member zulassen.
    Besser wäre jedoch ein "absoluter" Zeiger, dem alle Arten von Zeigern zuweisbar sind und an anderer Stelle beliebig verwendet werden kann.
    Das Wissen braucht ein Programmierer in jeder Sprache, jedoch wird er hier in C++ von seiner eigenlichen Aufgabe "unzumutbar abgelenkt".
    So genug!



  • /rant/ schrieb:

    int main()
    {
    foo thingy;
    void (foo::*mem_fun_ptr)() const = &foo::bar;
    (thingy.*mem_fun_ptr)();

    return 0;
    }[/cpp]

    MfG 😉

    Genau hier liegt das Problem beim Aufruf von Klassenfunktionen ich weiß nicht ob Klasse des Typs foo ist. Somit muss ich den Zeiger auf das Klassenobjekt mit übergeben und alles static abhandeln (keine Klassenfunktion). Nur der, der die Klasse foo geschrieben hat kennt die Klasse foo und kann den Member aus foo so aufrufen. ich kann das jedenfals nicht, denn ich weiß nicht mal, ob die Klasse des Members vom Typ foo ist. Ich kann nur sagen, daß die Funktion void ()(QWidget*) aussieht.



  • bastl schrieb:

    ...Jetzt habe ich vergessen wie man eine Funktionsadresse castet für einen Aufruf...

    Also mal ganz wild spekuliert: Willst Du einen Memberfunktion zu einer freien Funktion casten?
    Also sowas:

    struct A {
      void member();
    };
    
    int main() {
       A a;
       void (*f)();
       f = (caste irgendwie) a.member();
    ...
    

    falls ja: Vergiß es - geht nicht!
    (ist ein prinzipielles Problem - kein "muss man nur ein wenig rumschrauben-Problem)

    Schau mal bei den FAQs unter "Memberfunktion" nach ... da steht Einiges dazu drin. Auch, wie man Situationen, in denen man meint, das zu brauchen, vernünftig und sicher löst.

    Falls nicht: Vergessen, was ich schrieb.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Also mal ganz wild spekuliert: Willst Du einen Memberfunktion zu einer freien Funktion casten?
    falls ja: Vergiß es - geht nicht!
    (ist ein prinzipielles Problem - kein "muss man nur ein wenig rumschrauben-Problem)

    Ja, das geht natürlich nicht.
    Aber den Cast braucht man ja auch nicht. Die Funktion bleibt member, wird aber static deklariert, wie ein Thread. Jedoch habe ich da einen Fehler, die Funktion ist vom Typ void()(QWidget) und die übergebene Member-Addresse dann vom Typ void*()(QWidget)! Und dann funzts, wenigstens bei mir jetzt.
    Nacher gibts die deteilierte Auflösung mit Code und so.



  • bastl schrieb:

    Simon2 schrieb:

    Also mal ganz wild spekuliert: Willst Du einen Memberfunktion zu einer freien Funktion casten?
    falls ja: Vergiß es - geht nicht!
    (ist ein prinzipielles Problem - kein "muss man nur ein wenig rumschrauben-Problem)

    Ja, das geht natürlich nicht....

    OK, wenn Dir das schon bekannt war, will ich nichts gesagt haben.

    Es ist halt in 95% dieser Fälle hier das Problem.

    Nicht für ungut,

    Simon2.



  • Hier also der Recall mit einem Zeiger auf eine Memberfunktion:

    UsedClass : Ist die Klasse die den Recall ausführt, bzw. die eine Funktion einer beliebigen anderen Klasse ausführen möchte.
    AnyClass : Ist irgend eine Klasse, die eine Klassenfunktion, Member, bereitstellt, die auf den Recall Typ aus UsedClass zutrifft. In diesem Beisbiel baut AnyClass auf die Basisclasse QWidget auf.

    UsedClass.h

    class UsedClass
       {
       ...
       struct Record
          {
          void *( *PTR_member )( QWidget* );   //Name dieses Zeigers ist "PTR_member"
          QWidget *w  //Zugehöriges Objekt, die die Funktion mit der Memberaddresse enthält
          }
    
       Record *records;
       int anzahl;
    
       ...
       int register_member( void*( *member )( QWidget* ), QWidget *w ); //gibt eine Registriernummer zurück.
       void resetWidget( int nummer );   //Diese Funktion führt den Recall aus.
       ...
       }
    

    UsedClass.cpp

    ...
    int UsedClass::register_member( void*( *member )( QWidget* ), QWidget *w )
       {
       Record *tmp = new Record[ anzahl + 1 ];
    
       int i = 0;
       while ( i < anzahl )
          {
          tmp[ i ] = records [ i ];
          i++;
          }
    
       anzahl ++;
       tmp[ i ].PTR_member = member;
       tmp[ i ].w = w;
       records = tmp;
       }
    
    void UsedClass::resetWidget( int nummer )
       {
       records[ nummer ].PTR_member( records[ nummer ].w );   //Recall
       } 
    ...
    

    AnyClass.h

    class AnyClass : public QWidget
       {
       ...
       volatile double MyAccessValues;   //Variablen, die in der Recall-Memberfunktion benützt werden. volatile = Wert wird sofort in diese Variable zurückgeschrieben und nicht in einem Register zwischengespeichert (Kodeoptimierung = aus)
       ...
       static void *reset( QWidget *w );   //Recall-Funktion, resetet z.B das Widget
       ...
       }
    

    AnyClass.cpp

    ...
    void *AnyClass::reset( QWidget *w )
       {
       AnyClass *ptr = (( AnyClass* ) w ); 
       ...
       ptr->MyAccessValues = 0;
       ...
       }
    ...
    

    Irgendwo dann im Programm:

    ...
    UsedClass *UsedDialog = new UsedClass(...);   //Ein Object (UsedDialog) von UsedClass wird erstellt 
    ...
    AnyClass *mywidget = new AnyClass(...)   //Ein Object (mywidget) von AnyClass wird erstellt 
    ...
    meinenummer = UsedDialog->register_member(  &mywidget->reset, mywidget );
    ...
    UsedDialog->resetWidget( meinenummer );   //Recall aus UsedDialog von mywidget->reset()
    ...
    

    Also der, der die UsedClass in seinem Programm benützt, muss folgendes einhalten:
    -die Recallfunktion die er übergibt muss dem erwarteten Typ entsprechen
    -den Zeiger den er zurückbekommt muß er neu "casten" (( SeineKlasse* ) Zeiger ) um auf Klassenelemente zuzugreifen
    -die Memberfunktion die er übergibt muss static deffiniert sein.


Anmelden zum Antworten