2017-07-28 8 views
0

私はC言語の関数と呼ばれる持っている:私はこのような関数を呼び出すことができラムダ式などから関数ポインタを取得する方法は?

struct A { 
    static void CallBack(int i) { 
     A::count = i; 
    } 
    static count = 0; 
}; 

f_api(&A::CallBack) 

f_api(void(*callback)(int)) 

を、私は、コールバックのための静的クラスメソッドを持っています

しかし、複数のAオブジェクトを作成する必要があるため、コールバックを非静的に変更する必要があります。

しかし、f_api()の定義を変更することはできません。

私はラムダ使用してみました:

f_api([this](int i)->void{this->count = i;})` 

をしかし、私は単純な関数ポインタにキャプチャとラムダを変換することはできませんので、これは、失敗しました。

std::bind()f_api()の定義のために仕事もできません。

どうすればいいですか?ラムダ式から関数ポインタを取得するにはどうすればよいですか?回避策はありますか?

+0

あなたはすでにラムダを解決策として除外しています。だから、なぜそれについてもう一度尋ねていますか?いずれの場合でも、APIはコールバックにユーザー定義の値を渡すことを許可しますか?もしそうなら、それを使って 'this'ポインタを渡してください。それ以外の場合は、低レベルのサンクを使用せずにSOLになります。 –

+0

あなたができることは何もありません。メンバ関数ポインタから正規関数ポインタを生成するための標準的なツールはありません。コールバックAPIを変更できない場合は、何らかの理由で通常の関数を使用してコールバックをルーティングするしかありません。 – AnT

+0

@SilvioMayoloそれは少し違いがあります。他人を助けるかもしれない解決策を投稿しますが、それは私の役に立たないものです。 –

答えて

3

C APIを変更できない場合は、この状況について多くのことを行うことはできません。 C関数は、関数パラメータとして渡す必要があるすべての情報を必要とするためです。

あなたはどのキャプチャなしのラムダは、暗黙的に関数ポインタに変換することができ、次の

void (*ptr)() = []() {} 

で関数ポインタにラムダを変換することができます。しかし、値を取り込むラムダは、(メンバー変数の形で)余分な状態を持つため、関数ポインタに変換することはできません。

Cでこの問題を解決する通常の方法は、void*パラメータです。 pthread_createの機能を見てください。スレッド開始関数は、「コンテキスト」を指すvoid*パラメータを持つ関数を受け入れます。あなたの状況におけるこのコンテキストは、メソッドを呼び出すインスタンスのようなものになる可能性があります。

しかし、C APIを変更できない場合は、関数ポインタに関して多くのことを行うことはできません。あなたができる唯一のことは、変数をグローバルにし、それらを使って関数ポインタのメソッドを呼び出すことです。

+0

「変数をグローバルにする」と、ミューテックスなどのものを守る – Caleth

0

これは私が考えているものです: おそらく、私はラムダから関数ポインタを取得することでそれを行うことはできません。しかし、私はそう私ができる

template<unsigned int ClassCount> 
struct A { 
    static void CallBack(int i) { 
     A::count = i; 
    } 
    static int count; 
}; 

template<unsigned int ClassCount> 
int A<ClassCount>::count = 0; 

...いくつかの他のダニがマルチとしては、この問題を回避するために取得するために実行します。

f_api(&A<0>::CallBack); 
std::cout << A<0>::count << std::endl; 
f_api(&A<1>::CallBack); 
std::cout << A<1>::count << std::endl; // A<0>::count is different from A<1>::count 

これは、悲しげにしかし、ではないいくつかのケースでは潜在的な解決策になります鉱山で

関連する問題