class メンバー関数をコールバックとして渡したい
コールバック関数を引数に取るライブラリの関数に、自作クラスのメンバー関数を渡したいのですがうまくいきません。
どこが悪いのかご指摘をお願いいたします。
【やった事】
① ラムダ関数で渡すとメンバ変数にアクセスできないので
② std::bind
でラップしてみたがコンパイルエラーになる。
error: cannot convert 'std::_Bind<std::_Mem_fn<void (test_class::*)(unsigned char*, unsigned char)>(test_class*, std::_Placeholder<1>, std::_Placeholder<2>)>' to 'esp_now_send_cb_t {aka void (*)(unsigned char*, unsigned char)}' for argument '1' to 'int esp_now_register_send_cb(esp_now_send_cb_t)'
【実現したい事】
自作クラスのメンバー関数をコールバックとして渡したい。
【テストコード】
espnow.h の中から抜粋
typedef unsigned char u8;
typedef void (*esp_now_send_cb_t)(u8 *mac_addr, u8 status);
int esp_now_register_send_cb(esp_now_send_cb_t cb);
test_class.h
class test_class
{
public:
uint8_t val = 88;
test_class() {};
void initialize();
void send_cb(uint8_t* macaddr, uint8_t status);
};
test_class.cpp
void test_class::initialize()
{
Serial.println("initialize()");
// esp_now_register_send_cb() へ send_cb() を渡したい。
// ① このコードではコンパイルエラーは出ないが val にアクセスできない。
esp_now_register_send_cb([](uint8_t* macaddr, uint8_t status) {
Serial.print("esp_now_register_send_cb([]) : val = ");
// Serial.println(val); // コメント解除するとエラー
});
// ② std::bind を使って見たが 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); // 機能している
esp_now_register_send_cb(func); // コメント解除でコンパイルエラー
// error: cannot convert 'std::_Bind<std::_Mem_fn<void (test_class::*)(unsigned char*, unsigned char)>(test_class*, std::_Placeholder<1>, std::_Placeholder<2>)>' to 'esp_now_send_cb_t {aka void (*)(unsigned char*, unsigned char)}' for argument '1' to 'int esp_now_register_send_cb(esp_now_send_cb_t)'
}
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 <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
test_class test;
void setup()
{
Serial.begin(115200);
test.initialize();
}
void loop() {}
【環境】
WIndows 10
Arduino IDE 1.8.3
WSP8266 SDK 2.3.0
ご指摘、ご助言をよろしくお願いいたします。
【ご回答を頂いて】
C++初心者として同じ初心者プログラマの方々のために残しておきたいと思います。
この問題への解決にはC言語の「関数ポインタ」とC++言語の「メンバ関数ポインタ」の関数構造の違いを理解する必要がありました。
この違いについて初心者の私が説明するより(と、言うよりできない...)「c言語の関数ポインタとメンバ関数ポインタの違い」で検索すると詳細に説明又は応用解決に向けたサイトがたくさん出てきます。
初心者は問題解決に繋げる為のキーワードがわからない(又は連想できない)ので壁にぶつかって足踏みしてしまいます。
そんな時、stackoverflowの皆さんのアドバイスで解決への方向が見いだせるのです。
そんなstackoverflowで回答を寄せられている皆さんをいつも尊敬のまなざしで見ています。
早く初心者を脱して他の皆さんのお役に立てるように精進したいと思います。(まだまだ遠い...)
774RRさん、Hidekiさんありがとうございます。