68739


ESP32というCPUの開発環境上のBLEを扱おうと思っているのですが  
その中でコールバッククラスの扱いがわからなくて困っています  
VSCode + Platoform IOと言う環境です  
もとはAruduino形式のプログラムです(setupとloopがあらかじめ決められている)

元のプログラムではクラスでは無く、直接CPP上で記載されていて、プログラムは以下のようになっています

[code]

    //データを受信するとMyCallbaksがコールされ、onWrite関数内の命令を実行する
    //https://dev.classmethod.jp/articles/esp32_ble_debug_tool/
    //こちらのサンプルを使用
    class MyCallbacks: public BLECharacteristicCallbacks {//●コールバッククラスの本体
        void onWrite(BLECharacteristic *pCharacteristic) {//●onWriteが元のクラス内でvirtualで宣言されていて、この関数を自作して受信したデータの値を取り出す
          uint8_t* iData = pCharacteristic->getData();
          char str[100];
    
          for(int i=0;i<100;i++){
            sprintf(str,"data=%2x",*iData);
            iData++;
            Serial.print(str);
            Serial.print(" ");
          }
        }
    };
    
    pCharacteristic->setCallbacks(new MyCallbacks());//●ここでコールバッククラスを登録
    
[/code]

それをBLE関連のクラスにまとめてみようと思ったのですが

  1. **BLECharacteristicCallbacks** の中身の **onWrite** をヘッダファイルでは無く、  
CPPファイル側に記述したい

  2. **BleOreyou** クラスに値を渡す

と言うところで躓いています  
以下のように記述してみたのですがそこから先がどのように記述すればいいのか・・・

[code]

    Class BleOreyou{
    public:
        void OnWrite2(BLECharacteristic *pCharacteristic);
    
    //..省略
        class MyCallbacks: public BLECharacteristicCallbacks {
            void onWrite(BLECharacteristic *pCharacteristic) {//●この関数をcpp側に記述したい
                OnWrite2(pCharacteristic);                    //●BleOreyouクラスに渡してデータ操作、他のクラスへのイベントの起点にしたい
    #if 0
    
          uint8_t* iData = pCharacteristic->getData();
          char str[100];
    
          for(int i=0;i<100;i++){
            sprintf(str,"data=%2x",*iData);
            iData++;
            Serial.print(str);
            Serial.print(" ");
          }
    #endif
        };
    }
    
[/code]


CC BY-SA 4.0
2020-07-18T15:45:17.943
68713
2020-07-20T00:18:37.437
2020-07-18T17:16:15.233
3060
10098
question
c++ arduino bluetooth-lowenergy
C++の継承したクラスをコールバッククラスとして引数として渡しその中の関数をわかりやすく記述したい


A1. そもそも論として `virtual`
な関数をヘッダファイルにて関数定義してもインライン展開されることは期待できない（というより不可能）なので、ごく普通に「ヘッダファイルでクラス定義とメンバ関数宣言」「
CPP ファイルでメンバ関数定義」すればよいだけのことです。

\-- hoge.h --

[code]

    // クラス定義
    class derived1_type : public base_type {
        // メンバ関数宣言
        virtual void OnEvent(event_arg_type& ev);
    };
    
[/code]

\-- hoge.cpp ---

[code]

    #include "hoge.h"
    void derived1_type::OnEvent(event_arg_type& ev) {
        // 何か処理
    }
    
[/code]

A2. なにをどう渡すのか微妙に不明ですが、この手のコールバックの仕組みというのは

ライブラリというかフレームワークというか側に

[code]

    bool framework_type::register_callback(base_type& r) { ... }
    
[/code]

のような関数があるのが普通です。となると

コールバックしてもらう側（フレームワークのユーザー）の責務は

  * `base_type` 派生クラスのインスタンスを用意する（コールバックをしてもらう必要がある間ずっと有効でなければならない：ウィンドウのメンバとかにする必要がある）
  * `register_callback()` にその参照を渡してフレームワーク内に保持してもらう
  * コールバックが不要になったら `unregister_callback()` などの手段でやめてもらう

コールバックする側（フレームワーク自体）の処理は

  * 登録削除は先の説明と同等
  * コールバック一覧に登録されている `this` の仮想関数を呼び出す

つまりフレームワーク側の実装例は

[code]

    for (base_type& c : callbacklist) {
        c.OnEvent(ev);
    }
    
[/code]

（当該 `BLECharactaristicCallbacks` の仕様は未調査）

なのであなたのすべきことは

  * `MyCallbacks` インスタンスを生成してずっと保持する
  * `MyCallbacks` インスタンスをコールバックに登録する（以下略）

`BleOreyou` に当該 `MyCallbacks` インスタンスを保持しておけば何も悩むことはないような気がします。っていうか
`MyCallbacks` を `BleOreyou` から分離して別クラスにするから意味なく悩ましくなっているだけの疑いが残ります。


CC BY-SA 4.0
2020-07-20T00:10:00.853
68739
2020-07-20T00:18:37.437
2020-07-20T00:18:37.437
8589
8589
68713
answer