I want to pass a member function of my own class to a function in the library that takes the callback function as an argument, but it doesn't work.
Please point out what's wrong with you.
[What I did]
①
Because the member variable is not accessible when passed by the lambda function.
② std::bind
attempts to wrap but fails to compile.
error:cannot convert'std::_Bind<std::_Mem_fn<void(test_class::*)(unsigned char*, unsigned char)>(test_class*, std:::_Placeholder<1>, std:_Placeholder_lt;2>>>>
】What I want to realize したい
I want to pass my own class member function as a callback.
コードTest Code br
Excerpts from espnow.h
typedef unsigned charu8;
typeedef void (*esp_now_send_cb_t) (u8*mac_addr, u8status);
intesp_now_register_send_cb(esp_now_send_cb_tcb);
test_class.h
class test_class
{
public:
uint8_tval=88;
test_class(){};
void initialize();
void send_cb(uint8_t*macaddr,uint8_t status);
};
test_class.cpp
void test_class::initialize()
{
Serial.println("initialize()");
// I want to pass send_cb() to esp_now_register_send_cb().
// このThere is no compilation error with this code, but I cannot access the val.
esp_now_register_send_cb([](uint8_t*macaddr,uint8_t status){
Serial.print("esp_now_register_send_cb([]):val=");
// Serial.println(val);// Uncomment Error
});
// st I tried using std::bind, but I couldn't give it to esp_now_register_send_cb().
auto func=std::bind(&test_class::send_cb, this, std::placeholders::_1, std::placeholders::_2);
uint8_t macaddr[] = {0x09, 0x00, 0xA6, 0x18, 0x11, 0xBC};
func(macaddr,val);// functioning
esp_now_register_send_cb(func); // Uncomment Compilation Error
// error:cannot convert'std::_Bind<std::_Mem_fn<void(test_class::*)(unsigned char*, unsigned char)>(test_class*, std::_Placeholder<1>, std::_Placeholder<2>tend_to_spond;vd:'to_s
}
void test_class::send_cb(uint8_t*macaddr,uint8_t status)
{
Serial.printf("send_cb():%d:%d\n", macaddr[0], status);
}
test.ino
#include<arduino.h>
# include <ESP8266 WiFi.h>
US>extern "C" {
# include <espnow.h>
}
test_class test;
void setup()
{
Serial.begin (115200);
test.initialize();
}
void loop(){}
[Environment]
Windows 10
Arduino IDE 1.8.3
WSP8266SDK 2.3.0
Please give us your advice.
ごPlease reply br
As a C++ beginner, I would like to keep it for the same beginner programmers.
To solve this problem, we needed to understand the difference in function structure between the "function pointer" in C language and the "member function pointer" in C++ language.
As a beginner, I can't explain this difference (or, I can't say...) If you search for the difference between function pointers and member function pointers in c language, you will find many sites for detailed explanations or application solutions.
Beginners don't understand (or can't associate) keywords to solve problems, so they run into a wall and stomp.
At that time, the advice of stackoverflow staff will help us find a way to solve the problem.
I always look at all of you who have received responses through stackoverflow with respect.
I'll try my best to get out of the way and help others. (It's still a long way off...)
774RR, Hideki, thank you.
In the old days, MFC used the following procedure, but if esp_now_register_send_cb
cannot be changed, this method cannot be taken.Just for your information.
The non-static member function takes the implicit argument this
, so the calling procedure is incompatible at the assembly level with questions tagged with this, which means that normal functions and calling procedures are compatible.
typedef void (*esp_now_send_cb_t) (u8*mac_addr, u8status);
is a pointer to a normal function with c, so you cannot point to any non-static member function in the class.
If you want to call back the class's non-static member functions,
this
).this
to call non-static member functionsTherefore, this
needs to be delivered separately, and the implementation looks like this
class test_class{
static int CallbackSugarFunc(void*arg){
return reinterpret_cast<test_class*>(arg)->callbackfunc();
}
int callbackfunc();
};
Library side to register callback is also
typedefint(*callback_entry_func)(void*arg);
int register_callback(callback_entry_funcf, void*arg_to_callbackfunc);
As shown in , you can pass additional void*
, so you can pass this
when registering.
void test_class::initialize(){
register_callback(&test_class::CallbackSugarFunc, this);
}
If the library does not have a way to pass this
as an additional argument, you should create another class to manage the callback list and keep the this
list for callback.
c#delegate
manages this
and pointers to non-static member functions as a set.As expected, it's a late-stage language. c++ complements the deficiencies.
Unfortunately, I don't think so.
A function created with std::bind
has the same call as a normal function, but it cannot be a function pointer because the internal structure is completely different.
The lambda function can be used as a normal function without capturing variables.However, if you capture this so that you can access the member variable, it is no longer a normal function, so you cannot pass it to esp_now_register_send_cb
.
Best of all, modify esp_now_register_send_cb
to
intesp_now_register_send_cb(std::function<void(u8*,u8)>cb);
If it is an external function, you cannot change it in the first place.
Why don't you create an independent callback function, where you receive a callback and call the member function of the registered object?
For your information, the capture of this is
[this](uint8_t*macaddr,uint8_t status){
Serial.print("esp_now_register_send_cb([]):val=");
Serial.println(this->val);
}
You can do the following:
582 PHP ssh2_scp_send fails to send files as intended
619 Uncaught (inpromise) Error on Electron: An object could not be cloned
578 Understanding How to Configure Google API Key
573 rails db:create error: Could not find mysql2-0.5.4 in any of the sources
613 GDB gets version error when attempting to debug with the Presense SDK (IDE)
© 2024 OneMinuteCode. All rights reserved.