Frage zu Funktionspointer in Strukturen



  • Hallo, ich versuche gerade einen Funktionspointer in einer Struktur anzulegen, um so etwas wie eine Klasse wie in C++ zu erreichen.Vorne weg, ich kann nur in C programmieren und mir ist bewusst das so etwas in C++ leichter zu realisieren ist.

    Ok kommen wir zum Thema:

    Erst einmal etwas was bei mir gut funktioniert:

    void turnledon();
    
    struct hallo{
    	void (*turnledon)();
     };
    
    void main(){
    struct hallo test;
    test.turnledon = turnledon;  // Initialisierung der Struktur
    test.turnledon();
    }
    

    Das funktioniert.
    Soweit so gut, aber ich möchte den Funktionspointer eigentlich noch in einer separaten struktur haben, so wie das:

    void turnledon();
    
     struct hallo{
     	struct halloMT *mt;
     };
     struct halloMT{
            void (*turnledon)();
     };
    
    void main(){
    struct hallo test;
    test.mt->turnledon = turnledon;
    test.mt->turnledon();
    }
    

    Mit diesem Code schaffe ich es einfach nicht, dass die Leds angehen.

    Kann mir da vielleicht einer weiterhelfen, ich komme an der Stelle einfach nicht weiter. Mein Compiler beschwert sich auch nicht, von daher tappe ich momentan im Dunkeln.

    Gruß
    theflasher



  • Ich sehe keinen Fehler, vielleicht solltest du mal deine Hardware prüfen, ansonsten setze an die entsprechende Stelle in ledon mal eine Prüfausgabe.



  • Der Debugger ist der Beste Freund des Programmieres... 😃
    Nebenbei gesagt, deine Code scheint keine Fehler zu haben, da bei mir kein Fehler auftritt.
    Das einzige was Falsch ist ist

    void main(){
    

    richtig wäre:

    int main(void){
    

    wo genau tritt der Fehler auf? Und in welcher Form äussert er sich?
    gruss binggi



  • ok, werde das gleich mal versuchen.
    Hier noch ein kleiner Einblick in mein ganzes Programm. In der Main wird der InitTask gestartet und darin wird dann der Funktionspointer aufgerufen.
    Ich habe das ganze einmal im Debugger getestet und sobald ich in der Funktion InitTask in die LED_Unset_All() Funktion komme, stürzt der Controller ab.
    Muss das einmal weiter untersuchen. Vermutlich stimmt etwas mit der Anweisung davor nicht.

    void turnledon(void);
    void InitTask  (void* pdata);
    
     struct hallo{
     	struct halloMT *mt;
     };
     struct halloMT{
     void (*turnledon)();
     };
    
    int main(void)
    {
      SystemInit();
      LED_Init();
      CoInitOS();
      InitTaskID = CoCreateTask (InitTask,0,1,&InitTaskStk[128-1],128); 
      CoStartOS();   
    }
    
    void turnledon()
    {
    	LED_Set_All();	
    }
    
    void InitTask(void* pdata)
    {	 
    	struct hallo test;
    	test.mt->turnledon = turnledon;
    
    	LED_Unset_All();
    
    	while(1)    //hier tritt der Fehler auf
    	{
    		test.mt->turnledon();
    
    	}
    }
    


  • "*mt" in "struct hallo" ist ein Zeiger auf eine "struct halloMT". Da fehlt noch ein malloc. Oder einfach aus "*mt" nur "mt" machen.



  • Bist du dir sicher, dass deine Hardware die Endlosschleife while(1) verkraftet?



  • Binggi schrieb:

    Das einzige was Falsch ist ist

    void (*turnledon)(); sollte auch noch void (*turnledon)(void); sein auch wenn das nicht der Grund ist, warum es nicht funktioniert.



  • Versuch einmal der Code...

    #include <stdio.h>
    #include <string.h>
    
    void turnledon();
    
     struct hallo{
         struct halloMT *mt;
     };
     struct halloMT{
            void (*turnledon)();
     };
    
    int main(void){
    struct hallo test;
    test.mt->turnledon = turnledon;
    test.mt->turnledon();
    return 0;
    } 
    void turnledon()
    {
        printf("Test");
    }
    

    Sollte ohe Fheler durchlaufen



  • Merker hat richtig bemerkt, auch wenn es scheinbar niemand gemerkt hat, dass

    test.mt->turnledon = turnledon;
    

    nicht funktioniert, solange test.mt nicht initialisiert ist. Möglich:

    int main(void){
      struct hallo   test;
      struct halloMT test_mt;
    
      test.mt = &test_mt;
      test.mt->turnledon = turnledon;
      test.mt->turnledon();
    
      return 0;
    }
    

    Oder die Struktur etwas anpassen und so verfahren:

    void turnledon(void);
    
    struct halloMT{
      void (*turnledon)(void);
    };
    
    struct hallo{
      struct halloMT mt;
    };
    
    int main(void) {
      struct hallo test;
    
      test.mt.turnledon = turnledon;
      test.mt.turnledon();
    
      return 0;
    }
    


  • Also erst einmal vielen Dank für eure Hilfe, mir wurde wirklich weitergeholfen.
    Ich habe jetzt im Grunde zwei Lösungen.

    1.im struct hallo gibt es keinen Pointer mehr auf mt.

    void turnledon(void);
    void InitTask  (void* pdata);
    
     struct hallo{
         struct halloMT mt;
     };
     struct halloMT{
     void (*turnledon)();
     };
    
    int main(void)
    {
      SystemInit();
      LED_Init();
      CoInitOS();
      InitTaskID = CoCreateTask (InitTask,0,1,&InitTaskStk[128-1],128);
      CoStartOS();  
    }
    
    void turnledon()
    {
        LED_Set_All();   
    }
    
    void InitTask(void* pdata)
    {     
        struct hallo test;
        struct halloMT test_mt;
        test.mt = test_mt;
        test.mt.turnledon = turnledon;
    
        LED_Unset_All();
    
        while(1)   Lösung ohne Pointer
        {
            test.mt.turnledon();
    
        }
    }
    

    2. Lösung mit Pointer im struct hallo

    void turnledon(void);
    void InitTask  (void* pdata);
    
     struct hallo{
         struct halloMT *mt;
     };
     struct halloMT{
     void (*turnledon)();
     };
    
    int main(void)
    {
      SystemInit();
      LED_Init();
      CoInitOS();
      InitTaskID = CoCreateTask (InitTask,0,1,&InitTaskStk[128-1],128);
      CoStartOS();  
    }
    
    void turnledon()
    {
        LED_Set_All();   
    }
    
    void InitTask(void* pdata)
    {     
        struct hallo test;
        struct halloMT test_mt;
        test.mt = &test_mt;
        test.mt->turnledon = turnledon;
    
        LED_Unset_All();
    
        while(1)   Lösung ohne Pointer
        {
            test.mt->turnledon();
    
        }
    }
    

    Jetzt wäre vielleicht noch die Frage was effizienter ist. Am Ende wäre es schön, wenn es einen halloMT struct gäbe und alle anderen hallo structs greifen über diesen auf die Funnktionen zu. Damit ich im Grunde nicht ständig neue halloMT structs anlegen muss.
    Gruß theflasher



  • Binggi schrieb:

    Der Debugger ist der Beste Freund des Programmieres... 😃

    Und ich dachte immer das ist der Verstand.


Anmelden zum Antworten