[Arduino-Cpp] Void (xy::*) zu void (*)

  • C++

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    [Arduino-Cpp] Void (xy::*) zu void (*)

    Hallo Forum!

    Ich arbeite mal (ausnahmsweise) wieder mit Arduino, da ich, ganz ehrlich, nicht der beste in
    Arduino C++ stehe ich vor einem Problem:

    Ich habe "meine" (eig. musste ich sie nur von WiFi auf Ethernet umschreiben) Bibliothek diese hat die Klasse WemoSwitch:

    C-Quellcode

    1. #ifndef WemoSwitch_H
    2. #define WemoSwitch_H
    3. #include <Arduino.h>
    4. #include <Ethernet.h>
    5. #include "CallbackFunction.h"
    6. #include "WebServer.h"
    7. class WemoSwitch {
    8. private:
    9. WebServer *server = NULL;
    10. EthernetUDP UDP;
    11. String serial;
    12. String persistent_uuid;
    13. String device_name;
    14. unsigned int localPort;
    15. TaskFuncPtr onCallback;
    16. TaskFuncPtr offCallback;
    17. void startWebServer();
    18. void handleEventservice(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete);
    19. void handleUpnpControl(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete);
    20. void handleRoot(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete);
    21. void handleSetupXml(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete);
    22. void handleUnknown(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete);
    23. public:
    24. WemoSwitch();
    25. WemoSwitch(String alexaInvokeName, unsigned int port, TaskFuncPtr onCallback, TaskFuncPtr offCallback);
    26. ~WemoSwitch();
    27. String getAlexaInvokeName();
    28. void serverLoop();
    29. void respondToSearch(IPAddress& senderIP, unsigned int senderPort);
    30. };
    31. #endif

    Und den "richtigen" Code:
    Spoiler anzeigen

    C-Quellcode

    1. #include "WemoSwitch.h"
    2. #include "Ethernet.h"
    3. #include "CallbackFunction.h"
    4. #include "WebServer.h"
    5. //<<constructor>>
    6. WemoSwitch::WemoSwitch(){
    7. //Serial.println("default constructor called");
    8. }
    9. //WemoSwitch::WemoSwitch(String alexaInvokeName,unsigned int port){
    10. WemoSwitch::WemoSwitch(String alexaInvokeName, unsigned int port, TaskFuncPtr oncb, TaskFuncPtr offcb){
    11. uint32_t uniqueSwitchId = "MSODIEJFIELASD123123" + port;
    12. char uuid[64];
    13. sprintf_P(uuid, PSTR("38323636-4558-4dda-9188-cda0e6%02x%02x%02x"),
    14. (uint16_t) ((uniqueSwitchId >> 16) & 0xff),
    15. (uint16_t) ((uniqueSwitchId >> 8) & 0xff),
    16. (uint16_t) uniqueSwitchId & 0xff);
    17. serial = String(uuid);
    18. persistent_uuid = "Socket-1_0-" + serial+"-"+ String(port);
    19. device_name = alexaInvokeName;
    20. localPort = port;
    21. onCallback = oncb;
    22. offCallback = offcb;
    23. startWebServer();
    24. }
    25. //<<destructor>>
    26. WemoSwitch::~WemoSwitch(){/*nothing to destruct*/}
    27. void WemoSwitch::serverLoop(){
    28. int len = 64;
    29. char buff[len];
    30. server->processConnection(buff, &len);
    31. }
    32. void WemoSwitch::startWebServer(){
    33. server = new WebServer("", localPort);
    34. server->setFailureCommand(&handleUnknown);
    35. server->setDefaultCommand(&handleRoot);
    36. server->addCommand("setup.xml", &handleSetupXml);
    37. server->addCommand("upnp/control/basicevent1.xml", &handleUpnpControl);
    38. server->addCommand("eventservice.xml", &handleEventservice);
    39. server->begin();
    40. UDP.begin(localPort);
    41. /**
    42. server->on("/", [&]() {
    43. handleRoot();
    44. });
    45. server->on("/setup.xml", [&]() {
    46. handleSetupXml();
    47. });
    48. server->on("/upnp/control/basicevent1", [&]() {
    49. handleUpnpControl();
    50. });
    51. server->on("/eventservice.xml", [&]() {
    52. handleEventservice();
    53. });
    54. //server->onNotFound(handleNotFound);
    55. server->begin();
    56. Serial.println("WebServer started on port: ");
    57. Serial.println(localPort);
    58. **/
    59. }
    60. void WemoSwitch::handleUnknown(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
    61. {
    62. server.httpFail();
    63. }
    64. void handleEventservice(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete){
    65. Serial.println(" ########## Responding to eventservice.xml ... ########\n");
    66. String eventservice_xml = "<scpd xmlns=\"urn:Belkin:service-1-0\">"
    67. "<actionList>"
    68. "<action>"
    69. "<name>SetBinaryState</name>"
    70. "<argumentList>"
    71. "<argument>"
    72. "<retval/>"
    73. "<name>BinaryState</name>"
    74. "<relatedStateVariable>BinaryState</relatedStateVariable>"
    75. "<direction>in</direction>"
    76. "</argument>"
    77. "</argumentList>"
    78. "</action>"
    79. "</actionList>"
    80. "<serviceStateTable>"
    81. "<stateVariable sendEvents=\"yes\">"
    82. "<name>BinaryState</name>"
    83. "<dataType>Boolean</dataType>"
    84. "<defaultValue>0</defaultValue>"
    85. "</stateVariable>"
    86. "<stateVariable sendEvents=\"yes\">"
    87. "<name>level</name>"
    88. "<dataType>string</dataType>"
    89. "<defaultValue>0</defaultValue>"
    90. "</stateVariable>"
    91. "</serviceStateTable>"
    92. "</scpd>\r\n"
    93. "\r\n";
    94. server.httpSuccess();
    95. server.print(eventservice_xml.c_str());
    96. //server->write(eventservice_xml.c_str());
    97. }
    98. void WemoSwitch::handleUpnpControl(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete){
    99. Serial.println("########## Responding to /upnp/control/basicevent1 ... ##########");
    100. //for (int x=0; x <= HTTP.args(); x++) {
    101. // Serial.println(HTTP.arg(x));
    102. //}
    103. //EthernetClient c = server->available();
    104. String request = "SAMPLE";
    105. Serial.print("request:");
    106. Serial.println(request);
    107. Serial.println("Responding to Control request");
    108. String response_xml = "";
    109. if(request.indexOf("<BinaryState>1</BinaryState>") > 0) {
    110. Serial.println("Got Turn on request");
    111. onCallback();
    112. response_xml = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
    113. "<s:Body>"
    114. "<u:SetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">"
    115. "<BinaryState>1</BinaryState>"
    116. "</u:SetBinaryStateResponse>"
    117. "</s:Body>"
    118. "</s:Envelope>\r\n"
    119. "\r\n";
    120. }
    121. if(request.indexOf("<BinaryState>0</BinaryState>") > 0) {
    122. Serial.println("Got Turn off request");
    123. offCallback();
    124. response_xml = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
    125. "<s:Body>"
    126. "<u:SetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">"
    127. "<BinaryState>0</BinaryState>"
    128. "</u:SetBinaryStateResponse>"
    129. "</s:Body>"
    130. "</s:Envelope>\r\n"
    131. "\r\n";
    132. }
    133. //server->write(response_xml.c_str());
    134. Serial.print("Sending :");
    135. Serial.println(response_xml);
    136. }
    137. void WemoSwitch::handleRoot(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete){
    138. //server->write("You should tell Alexa to discover devices");
    139. }
    140. void WemoSwitch::handleSetupXml(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete){
    141. Serial.println(" ########## Responding to setup.xml ... ########\n");
    142. IPAddress localIP = Ethernet.localIP();
    143. char s[16];
    144. sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
    145. String setup_xml = "<?xml version=\"1.0\"?>"
    146. "<root xmlns=\"urn:Belkin:device-1-0\">"
    147. "<specVersion>"
    148. "<major>1</major>"
    149. "<minor>0</minor>"
    150. "</specVersion>"
    151. "<device>"
    152. "<deviceType>urn:Belkin:device:controllee:1</deviceType>"
    153. "<friendlyName>"+ device_name +"</friendlyName>"
    154. "<manufacturer>Belkin International Inc.</manufacturer>"
    155. "<modelName>Emulated Socket</modelName>"
    156. "<modelNumber>3.1415</modelNumber>"
    157. "<manufacturerURL>http://www.belkin.com</manufacturerURL>"
    158. "<modelDescription>Belkin Plugin Socket 1.0</modelDescription>"
    159. "<modelURL>http://www.belkin.com/plugin/</modelURL>"
    160. "<UDN>uuid:"+ persistent_uuid +"</UDN>"
    161. "<serialNumber>"+ serial +"</serialNumber>"
    162. "<binaryState>0</binaryState>"
    163. "<serviceList>"
    164. "<service>"
    165. "<serviceType>urn:Belkin:service:basicevent:1</serviceType>"
    166. "<serviceId>urn:Belkin:serviceId:basicevent1</serviceId>"
    167. "<controlURL>/upnp/control/basicevent1</controlURL>"
    168. "<eventSubURL>/upnp/event/basicevent1</eventSubURL>"
    169. "<SCPDURL>/eventservice.xml</SCPDURL>"
    170. "</service>"
    171. "</serviceList>"
    172. "</device>"
    173. "</root>\r\n"
    174. "\r\n";
    175. //server->write(setup_xml.c_str());
    176. Serial.print("Sending :");
    177. Serial.println(setup_xml);
    178. }
    179. String WemoSwitch::getAlexaInvokeName() {
    180. return device_name;
    181. }
    182. void WemoSwitch::respondToSearch(IPAddress& senderIP, unsigned int senderPort) {
    183. Serial.println("");
    184. Serial.print("Sending response to ");
    185. Serial.println(senderIP);
    186. Serial.print("Port : ");
    187. Serial.println(senderPort);
    188. IPAddress localIP = Ethernet.localIP();
    189. char s[16];
    190. sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
    191. Serial.print("Creating Resonse ...");
    192. String response =
    193. "HTTP/1.1 200 OK\r\n"
    194. "CACHE-CONTROL: max-age=86400\r\n"
    195. "DATE: Sat, 26 Nov 2016 04:56:29 GMT\r\n"
    196. "EXT:\r\n"
    197. "LOCATION: http://" + String(s) + ":" + String(localPort) + "/setup.xml\r\n"
    198. "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
    199. "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n"
    200. "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
    201. "ST: urn:Belkin:device:**\r\n"
    202. "USN: uuid:" + persistent_uuid + "::urn:Belkin:device:**\r\n"
    203. "X-User-Agent: redsonic\r\n\r\n";
    204. Serial.println("Done!");
    205. Serial.print("Sending Packet...");
    206. UDP.beginPacket(senderIP, senderPort);
    207. UDP.write(response.c_str());
    208. UDP.endPacket();
    209. Serial.println("Done");
    210. Serial.println("Response sent !");
    211. }



    Nun gibt der Compiler (einige) Meldungen nach dem Schema:
    no known conversion for argument 2 from 'void (WemoSwitch::*)(WebServer&, WebServer::ConnectionType, char*, bool)' to 'void (*)(WebServer&, WebServer::ConnectionType, char*, bool)'

    Kurz: void(WemoSwitch::*) kann nicht in void(*) umgewandelt werden

    Was kann ich nun tun?

    Verschoben. ~Thunderbolt
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Thunderbolt“ ()

    Für mich sieht es so aus, als hättest du bei

    Quellcode

    1. ​void handleEventservice
    das WemoSwitch:: vor dem Methodennamen vergessen.

    Bei allen anderen hast du das so gemacht, und bei dem nicht.
    Es ist ja in der Header-Datei eingetragen, deswegen muss da das auch davor :)
    ~ Alex-Digital :D

    if(!Internet.VBP.Get<User>("Alex-Digital").IsOnline) this.Close(); :D
    @Alexander M.
    Danke dir,

    Ich hatte das WemoSwitch:: zu Testzwecken entfernt. Wenn ich es hinschreibe passiert das selbe.

    Der Fehler wird bei allen "handle"s geworfen.
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.
    Naja ist ja klar, der Callback ist nicht für Member-Methoden gedacht.
    Wenn du C++11 oder höher hast, dann kannst du über std::bind einfach den this-Pointer binden.
    Ansonsten musst du die Methode static machen. Falls du dann darin Zugriff auf dein WemoSwitch-Objekt brauchen solltest musst du irgendwie die Verknüpfung zwischen dem WebServer-objekt und deinem Objekt herstellen. Evtl. kannst du in WebServer ein custom userdata objekt angeben? Ansonsten sind maps eine Möglichkeit.(Es gibt auch mit Makrospielereien und Meta-programming Möglichkeiten statisch unterschiedliche Methoden zu erstellen um den this pointer zu binden, das ist aber ziemlich aufwendig und ohne boost würde ich das glaube ich auch nicht machen wollen :D)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl
    Also der Compiler ist GNU++11, also "der böse Bruder" von C++11, richtig?

    D.h. ich könnte den this pointer verwenden (gibt keine Compilerfehler :D)
    Aber wie genau meinst du das mit den this, wie soll ich es benutzen...

    Sorry für die etwas Dumme Frage, aber C++ ist nicht gerade meine stärke...
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.

    LuaX schrieb:

    C++ ist nicht gerade meine stärke...
    Dann arbeite doch mit C#.
    this ist doch der Pointer auf die aktuelle Klasse.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Nem, wenn ich auf einem AVR-Mikrocontroller C# laufen lassen könnte wäre ich überglücklich.
    Ok, das this auf die aktuelle Instanz der Klasse zeigt, leuchtet ein (is ja bei fast allen anderen Sprachen auch so).
    Aber,
    Was genau bringt mir jetzt der this pointer, mit dem wird aus void (*::*) ja auch nicht void (*). Oder doch?
    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.
    GNU++11 ist kein Compilername und auch keine Compilerversion. Du hast vmtl. etwas wie avr-gcc/avr-g++ 4.8 oder sowas.
    Die Frage ist wie ist der Compilerflag -std eingestellt. -std=gnu++11 oder -std=c++11. Wenn du das eine verwenden kannst, kannst du auch das andere verwenden. gnu++11 ist im Prinzip dasselbe wie c++11 mit ein paar zusätzlichen features die den C++11 Standard kaputt machen(also in diesem Sinne nicht unbedingt so toll).
    cplusplus.com/reference/functional/bind/
    Das musst du verwenden.

    C-Quellcode

    1. std::bind(function,this, ...)

    bei ... musst du den Parametern, die die Funktion hat Werte geben, bzw. in diesem Fall eben Platzhalter std::placeholders::_1 wobei die _1 der Index des Parameters ist, der nächste wäre also _2

    Edit: achja den this pointer gibt es schon von Anfang an in C++ und nicht erst seit C++11 :D
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @LuaX Nach meinem C++-Verständnis steht das this bei *::* für den ersten Stern.
    Die Funktion, für die der zweite Stern steht, muss dann noch spezifiziert werden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!