Go Down

Topic: Funktionsaufruf klappt nicht (Read 3780 times) previous topic - next topic

TERWI

Folgender Textauszug:
Code: [Select]

...
#include <Messenger.h>
#include <MegaStepper.h>  // meine Lib
...
MegaStepper MegStep = MegaStepper();
Messenger message = Messenger(',');
...
void messageCompleted()
{ ...
}
...
void setup()
{ ...
  MegStep.serParseMessage();                                   // <- A)
  message.attach(messageCompleted);                      // <- B)
//  message.attach(MegStep.serParseMessage);       // <- C)
//  message.attach(MegStep.serParseMessage());     // <- D)
}
...
void loop()
{ ...
}

So wie es da steht, wird kompiliert. D. h. Aufruf A) und B) klappt.
Die Funktionen "messageCompleted" und "serParseMessage" in meiner Lib sind absolut identisch, können auch leer sein.

Markiere ich jetzt mal B) aus und lasse statt dessen C) ausführen, gibt es diesen Fehler:
Serial_Test_2_ino.ino: In function 'void setup()':
Serial_Test_2_ino:105: error: no matching function for call to 'Messenger::attach(<unresolved overloaded function type>)'
C:\...\messenger/Messenger.h:28: note: candidates are: void Messenger::attach(void (*)())


Nehme ich D) statt C), wird so rumgemault:
Serial_Test_2_ino.ino: In function 'void setup()':
Serial_Test_2_ino:105: error: invalid use of void expression


Ich nix verstehn das.
To young to die - never to old for rock'n roll

Serenifly

D kann nicht funktionieren. Attach() will einen Function-Pointer so wie das aussieht (analog zu attachInterrupt), d.h. nur der Methoden-Name. Wenn du das () dran hängt ruft er die Funktion auf und versucht den Rückgabe-Wert zu übergeben.

Sieht irgendwo so aus als ob MegStep.serParseMessage überladen ist und er sich nicht entscheiden kann was er nehmen soll.

Du kannst den Pointer vielleicht erst mal per Hand definieren. Ich mache das bei mir so (vereinfacht):
Code: [Select]

void (*callback)();

callback = TriggerAlarm0;

Alarm.alarmRepeat(callback);


In der ersten Zeile kannst du den Pointer dann genau definieren. Hier könnte er dann kapieren, dass der Pointer auf eine Function ohne Argumente zeigt und muss nicht mehr raten was gemeint ist.

TERWI

Ein Aufruf von
 callback = MegStep.serParseMessage();  
ergibt hier:
Serial_Test_2_ino.ino: In function 'void setup()':
Serial_Test_2_ino:105: error: void value not ignored as it ought to be


Da ist nix überladen in der Lib - die Funktion gibts nur einmal.
To young to die - never to old for rock'n roll

Serenifly

#3
Jul 09, 2013, 02:11 pm Last Edit: Jul 09, 2013, 02:31 pm by Serenifly Reason: 1
Mhh, der Compiler denkt aber sie ist überladen. Wieso auch immer. Das ist die typische Fehlermeldung wenn er nicht weiß welche Funktion er nun nehmen soll.

Wobei das wieder falsch ist
Code: [Select]

callback = MegStep.serParseMessage();


Function-Pointer haben keine Klammern. Wenn du das schreibst ruft er die Methode auf und weist den Rückgabe-Wert der callback Variable u. Das gleiche Problem wie bei "D".

Der Aufruf eines Function-Pointers ohne Argumente geht so:
Code: [Select]

(*callback)();


Ich würde es so probieren:
Code: [Select]

void (*fp)();
fp = MegStep.serParseMessage;
message.attach(fp);

TERWI

Auruf
 callback = MegStep.serParseMessage;  
ergibt:
Code: [Select]

Serial_Test_2_ino:105: error: argument of type 'void (MegaStepper::)()' does not match 'void*'
To young to die - never to old for rock'n roll

Serenifly

#5
Jul 09, 2013, 02:30 pm Last Edit: Jul 09, 2013, 02:41 pm by Serenifly Reason: 1
Kannst du mal die Deklaration der serParseMessage-Funktion posten? Kann es sein dass die einen void-Pointer zurück gibt?
So richtig blicke ich jetzt auch nicht mehr durch :)

EDIT:
Sehe gerade was da überladen ist ist die attach-Funktion...und die will natürlich einen void Pointer. Keine Ahnung wieso das nicht geht.

TERWI

MegaStepper.h
(hab ich von Messenger.h abgeleitet)
Code: [Select]

#ifndef MegaStepper_h
#define MegaStepper_h

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class MegaStepper
{
.....

typedef struct
{
.....
} CMD_Record;

typedef struct
{
.....
} Motor_Data;

public:
  // --- MegaStepp - class
  MegaStepper();   // constructor
  ~MegaStepper();  // destructor

  // --- CMD: 001-049 - Serial communication
  void serParseMessage();
...

private:

  Motor_Data* Motor;
  int NumMotors;
};
#endif

MegaStepper.cpp
Code: [Select]

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "MegaStepper.h"


//###################################################################
// --- MegaStepp - class
//###################################################################
//-------------------------------------------------------------------
MegaStepper::MegaStepper()  // constructor
{
  Motor = NULL;
  NumMotors = 0;;
}

MegaStepper::~MegaStepper()  // destructor
{
  // free allocated memory
}

//###################################################################
// --- CMD: 001-049 - Serial communication
//###################################################################
//-------------------------------------------------------------------
void MegaStepper::serParseMessage()
{
// hier steht noch nix drin
}
.....

To young to die - never to old for rock'n roll

Serenifly

#7
Jul 09, 2013, 02:59 pm Last Edit: Jul 09, 2013, 06:51 pm by Serenifly Reason: 1
Ok, gerade mal Google bemüht, und das Problem hier scheint zu sein, dass es ein Pointer auf eine Methode in einer anderen Klasse ist. Das unterscheidet sich von normalen Function-Pointern (da ein versteckter this-pointer benötigt wird) und ist komplizierter. :) :(

http://www.parashift.com/c++-faq-lite/pointers-to-members.html
http://www.cplusplus.com/forum/beginner/11663/

Der Pointer müsste dann so aussehen (jedenfalls nach dem was da steht):
Code: [Select]

void (MegaStep::*fp)();
fp = MegStep::serParseMessage;
message.attach(fp);


Manchmal wird auch ein typedef empfohlen:
Code: [Select]

typedef void (MegaStepper::*FuncPtr)();
FuncPtr fp;


Am besten du Googelst da mal nach "pointer to member function" und "pointer to non static member function". Ich schreibe da auch nur gerade ab was ich dort lese :p

MaFu

Klassenmethoden und normale Funktionen sind zwei verschiedene Paar Schuhe.
@TERWI: das sollte Dir eigentlich klar sein, ist nämlich in Delphi auch so  ;)
_______
Manfred

TERWI

So ein Zirkus mache ich unter Delphi nicht.  :smiley-eek:
... das ist mir ehrlich gesagt zu hoch.
Hier klappt nix.
To young to die - never to old for rock'n roll

TERWI

Lesen bildet - kostet aber auch viel Zeit !
So geht es hier nun:
Code: [Select]

MegaStepper* obj_MegaStepper;

void _serParseMessage()
{
  obj_MegaStepper->serParseMessage();
}

void setup()
{
//  message.attach(messageCompleted); // der ursprüngliche Aufruf mit lokaler funktion
//  MegStep.serParseMessage();              // Die func in meiner Lib
  message.attach(_serParseMessage);     // Zuweisung für den Callback.
}

Nicht wahnsinnig elegant, aber tut.
Gefunden hier: // http://www.parashift.com/c++-faq/memfnptr-vs-fnptr.html
Alles andere mit typedef & Co. haut nicht hin.
To young to die - never to old for rock'n roll

Serenifly

Mhh, ich finde es recht elegant (wenn auch nicht kurz). Dadurch umgeht man schön den ganzen Mist um member/non-member functions :)

Das Problem ist eben dass selbst man einen Pointer auf die Funktion übergeben könnte, immer noch keine Referenz auf das ganze Objekt dort ist.

TERWI

#12
Jul 09, 2013, 08:03 pm Last Edit: Jul 09, 2013, 08:06 pm by TERWI Reason: 1
Manchmal sieht man's einfach nicht. Noch ne Deklaration gespart.
Geht doch auch direkt gleich so:
Code: [Select]

void _serParseMessage()
{
 MegStep.serParseMessage();              // Die func in meiner Lib
}

void setup()
{
//  message.attach(messageCompleted); // der ursprüngliche Aufruf mit lokaler funktion
 message.attach(_serParseMessage);     // Zuweisung für den Callback.
}

Ich glaube in letzter Konsequenz werde ich ohnehin den Messenger (in leicht abgewandelter Form) in meinen Stepper einbauen ...
Da hat sich dass dann was mit Callback und so.  ;)
To young to die - never to old for rock'n roll

Go Up