「C++の基礎 - コールバック関数」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(文字列「<source」を「<syntaxhighlight」に置換)
(文字列「</source>」を「</syntaxhighlight>」に置換)
 
27行目: 27行目:
     printf("Hello World!!");
     printf("Hello World!!");
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


70行目: 70行目:
     return clsInvoker->m_Data;
     return clsInvoker->m_Data;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>



2021年11月22日 (月) 19:44時点における最新版

コールバック関数とは

コールバックとは、プログラミングにおいて、他のコードの引数として渡されるサブルーチンである。
これにより、低レベルの抽象化層が高レベルの層で定義された関数(サブルーチン)を呼び出せるようになる。

C言語のサンプルコード

下記のサンプルコードにおいて、main() -> Hello() -> Show() の順番に呼ばれる機構をコールバックと呼ぶ。

 // main.c
 #include <stdio.h>
 
 void Hello(void (fnShow)(void));
 void Show(void);
 
 int main()
 {
    Hello(Show);
    return 0;
 }
 
 void Hello(void (fnShow)(void))
 {
    fnShow();
 }
 
 void Show(void)
 {
    printf("Hello World!!");
 }



C++言語のサンプルコード

下記のサンプルコードにおいて、CInvoker::Executeを呼び出すことでCInvoker::CallbackFuncがコールバックされる。

 // CInvoker.h
 class CInvoker
 {
    private:
       int m_Data;
  
    pubic:
       CInvoker();
       ~CInvoker();
       void Execute();
       static int CallbackFunc(void* userData); // コールバック関数
 }
 
 // CInvoker.cpp
 // コンストラクタ
 CInvoker::CInvoker() : m_Data(100)
 {
 }
 
 // デストラクタ
 CInvoker::~CInvoker()
 {
 }

 void CInvoker::Execute()
 {
    int result = 0;
    result = reinterpret_cast<CInvoker*>(this)->CallbackFunc(this);
 }
  
 // コールバック関数
 int CInvoker::CallbackFunc(void* clsObject)
 {
    CInvoker clsInvoker = reinterpret_cast<CInvoker*>(clsObject);
 
    return clsInvoker->m_Data;
 }



仕組み

C++のクラスでコールバックメソッドを実行するには静的(static)なメソッドにしなければならない。
静的(static)でないと、以下のコンパイルエラーが表示される。

仮想関数のアドレスを取ろうとしました

これは、クラスが生成されるまでメモリ上に展開されず、呼び出し元のメソッドがどのポインタを参照すればよいかわからないためエラーになる。
即ち、静的メソッドにしてポインタの位置を固定した後、reinterpret_castでアドレスの解釈を強制的に変更することで、
動的に取得したクラスメソッドにアクセスできるようになる。