関数ポインタ

function-pointer.png

コールバック関数
ファンクタ(関数オブジェクト)

Getting Started

関数ポインタの書き方

void (*関数ポインタ変数名)(引数の型名)

関数ポインタを代入するとき

どっちでもOk

関数ポインタ変数名=&関数名;
関数ポインタ変数名=関数名;

サンプルコード

#include <stdio.h>
void print(const char* _message,int _i){
    printf("[%d]%s",_i,_message);
}
void main(){
    void (*function_pt)(const char*,int);//関数ポインタ
    function_pt=&print;
    function_pt("hello I am miffy\n",7);
}

メンバ関数をコールバック関数にしたい場合

メンバ関数をコールバックする方法
メンバ関数は普通の関数と異なり、thisを暗黙のパラメータとして必要とするので、単純に関数ポインタだけを渡してもコールバックできない。
関数ポインタじゃなくて、C++の機能である関数オブジェクトを使ってファンクタアダプターを使うべき。
しかし、OpenGLみたいに、ライブラリ自体が関数ポインタを使ってる場合はどうしようもないよね。
こんな記事も発見[http://d.hatena.ne.jp/kazuhooku/20110126/1296031454 Cのコールバック関数をC++のメンバ関数]にバインディングする方法]
なので以下の方法を参照にすべし。
代替策?

CHoge* pHoge;//オブジェクトへのポインタ
LRESULT (CHoge::*pFunc)(int);//メンバ関数へのポインタ
//このようにすれば、その関数が呼び出せる
pHoge->*pFunc(3);

らしいけど、あんまりおすすめじゃないらしい。
理由は、コールバックする側にとって見れば、CHoge*とCHogeクラスのメンバ関数ポインタが渡されるとは事前にはわからないから。

グローバルなオブジェクト変数を使う方法

グローバル変数を介してコールバック関数にすることができる

OpenGLをライブラリ化するようなクラス

必要な関数を呼び出すファンクタのラッパークラスを作成する[1]ってことかな。

extern GLRender* gRender;
static void display(void ){
    gRender->render();
}
void GLRender::render(void)
{
    glClearColor(0.0/255.0,0.0/255.0,0.0, 0.f);
    //いつものように書く
    glutSwapBuffers();
}
void GLRender::start(int argc, char *argv[])
{
    glutInit(&argc, argv);
    .....
    glewInit();
    glutDisplayFunc(display);
    glutMainLoop();
}

使い方

GLRender* gRender;
void main(int argc, char *argv[]){
    gRender=new GLRender();
    gRender->start( argc,  argv);
}

こうやって作った関数をどうやって継承するか?が問題。

boostのfunctionとbindを使う方法


lambda

サポートサイト Wikidot.com lambda