Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use the callbackHandler inside the library #107

Open
robertgregor opened this issue Dec 15, 2020 · 4 comments
Open

How to use the callbackHandler inside the library #107

robertgregor opened this issue Dec 15, 2020 · 4 comments

Comments

@robertgregor
Copy link

Hi,
I have maybe similar issue as the others here.
I have a arduino library where I have a class, in which I want to use the handler:
RemoteHome.h
class RemoteHome {
public:
void handleSPIFFS(HTTPRequest * req, HTTPResponse * res);
}

Then in the RemoteHome.cpp I have:

void RemoteHome::handleSPIFFS(HTTPRequest * req, HTTPResponse * res) {
....
}
And I have in that class the method:

void RemoteHome::startWebServer() {
server = new HTTPServer();
ResourceNode *spiffsNode = new ResourceNode("", "", &RemoteHome::handleSPIFFS);
server->setDefaultNode(spiffsNode);
server->start();
if (server->isRunning()) {
LogTool::logSketch('I', PSTR("RemoteHome::setup"), PSTR("Http server is ready."));
}

Looks fine to me, but it will not compile:
Error downloading https://downloads.arduino.cc/packages/package_index.json
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\RemoteHome\src\RemoteHome.cpp: In member function 'void RemoteHome::startWebServer()':
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\RemoteHome\src\RemoteHome.cpp:788:68: error: no matching function for call to 'httpsserver::ResourceNode::ResourceNode(const char [1], const char [1], void (RemoteHome::)(httpsserver::HTTPRequest, httpsserver::HTTPResponse*))'
spiffsNode = new ResourceNode("", "", &RemoteHome::handleSPIFFS);
^
In file included from C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\esp32_https_server\src/HTTPServer.hpp:20:0,
from C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\esp32_https_server\src/HTTPSServer.hpp:15,
from C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\RemoteHome\src\RemoteHome.h:13,
from C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\RemoteHome\src\RemoteHome.cpp:9:
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\esp32_https_server\src/ResourceNode.hpp:18:3: note: candidate: httpsserver::ResourceNode::ResourceNode(const string&, const string&, void ()(httpsserver::HTTPRequest, httpsserver::HTTPResponse*), const string&)
ResourceNode(const std::string &path, const std::string &method, const HTTPSCallbackFunction * callback, const std::string &tag = "");
^
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\esp32_https_server\src/ResourceNode.hpp:18:3: note: no known conversion for argument 3 from 'void (RemoteHome::)(httpsserver::HTTPRequest, httpsserver::HTTPResponse*)' to 'void ()(httpsserver::HTTPRequest, httpsserver::HTTPResponse*)'
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\esp32_https_server\src/ResourceNode.hpp:16:7: note: candidate: httpsserver::ResourceNode::ResourceNode(const httpsserver::ResourceNode&)
class ResourceNode : public HTTPNode {
^
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\esp32_https_server\src/ResourceNode.hpp:16:7: note: candidate expects 1 argument, 3 provided

How can I make it working? Seems to me, that your code doesn't accept my method...

@fhessel
Copy link
Owner

fhessel commented Dec 15, 2020

Hi,

it's the same issue as in #90 or #105: If you want to use a method from a class, you need to somehow specify on which instance that method should be called. You can do such things with std::bind, but in 1.0.0, you cannot pass the result from that to the ResourceNode.

If you need that functionality now, switch from master to PR #91 as mentioned in this comment and use std::bind like described here. I will try to keep up with PR/Issues during holidays.

@robertgregor
Copy link
Author

Hi, Yes, this I did: esp32_https_server-feature-functional-callbacks.
But how can use std::bind?
I have tried this:
HTTPSCallbackFunction handler = std::bind(&RemoteHome::handleSPIFFS, std::placeholders::_1);
server->registerNode(new ResourceNode("/", "GET", handler));

But I have this error:
c:\users\gregorro\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-80-g6c4433a-5.2.0\xtensa-esp32-elf\include\c++\5.2.0\functional:1426:7: error: static assertion failed: Wrong number of arguments for pointer-to-member
static_assert(_Varargs::value
^
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\RemoteHome\src\RemoteHome.cpp: In member function 'void RemoteHome::startWebServer()':
C:\RH\Sources\RH\RemoteHomeArduinoSketches\WiFi_ESP32\libraries\RemoteHome\src\RemoteHome.cpp:790:20: error: conversion from 'std::_Bind_helper<false, void (RemoteHome::)(httpsserver::HTTPRequest, httpsserver::HTTPResponse*), const std::_Placeholder<1>&>::type {aka std::_Bind<std::_Mem_fn<void (RemoteHome::)(httpsserver::HTTPRequest, httpsserver::HTTPResponse*)>(std::_Placeholder<1>)>}' to non-scalar type 'httpsserver::HTTPSCallbackFunction {aka std::function<void(httpsserver::HTTPRequest*, httpsserver::HTTPResponse*)>}' requested
std::bind(&RemoteHome::handleSPIFFS, std::placeholders::_1);

@fhessel
Copy link
Owner

fhessel commented Dec 15, 2020

You need to stick to the exact syntax from the other PR.

Somewhere outside any function:

// Create a global instance of the RemoteHome class
RemoteHome myRemoteHome;

In your setup() or whereever you configure your server:

HTTPSCallbackFunction handler =
          std::bind(&RemoteHome::handleSPIFFS, &myRemoteHome, std::placeholders::_1, std::placeholders::_2);
server.registerNode(new ResourceNode("/", "GET", handler));

The first parameter of std::bind specified the function that should be called. The second parameter is a pointer to the instance on which it should be called (you also need to create such an instance, and make sure that it's valid for the whole lifetime of the server. That's why we created it in global scope above). The third and fourth parameters are placeholders. They will become the req and res parameter of the bound function. Since we have two parameters, you need to have two placeholders.

@robertgregor
Copy link
Author

robertgregor commented Dec 15, 2020

OKi, yes, shall be like that:
HTTPSCallbackFunction handler =
std::bind(&RemoteHome::handleSPIFFS, this, std::placeholders::_1, std::placeholders::_2);

Thanks!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants