グローバル
他の人が述べたように、グローバルが必要です(静的メンバーは変数 member として隠されているグローバルです)。もちろん、コールバックで異なるパラメーターを使用するために複数のオブジェクトが必要な場合は機能しません。
コールバックのコンテキスト パラメータ
AC ライブラリは、void *
または類似のコンテキストを提供する場合があります。その場合は、その機能を使用してください。
たとえば、ffmpeg ライブラリは、次のように定義されたデータを読み取るためのコールバックをサポートしています。
int(*read_packet)(void *opaque, uint8_t *buf, int buf_size);
パラメータはopaque
に設定できますthis
。コールバック内で、型 (クラスの名前) にキャストするだけです。
Calback のライブラリ コンテキスト パラメータ
struct
AC ライブラリは、そのオブジェクト (ポインター)を使用してコールバックを呼び出す場合があります。example
という名前の型を提供し、次のexample_t
ようなコールバックを定義するという名前のライブラリがあるとします。
callback(example_t *e, int param);
次に、その構造にコンテキスト(別名this
ポインター) を配置example_t
し、コールバックでそれを取得できる場合があります。
シリアル コール
その特定の C ライブラリを使用するスレッドが 1 つしかなく、ライブラリ内の関数を呼び出したときにのみコールバックをトリガーできる (つまり、ランダムな時点でトリガーされるイベントを取得しない) と仮定すると、グローバル変数を使用できます。 . あなたがしなければならないことは、各呼び出しの前に現在のオブジェクトをグローバルに保存することです。このようなもの:
object_i_am_working_with = this;
make_a_call_to_that_library();
object_i_am_working_with
このようにして、コールバック内でいつでもポインターにアクセスできます。これは、マルチスレッド アプリケーションや、ライブラリがバックグラウンドでイベントを自動的に生成する場合 (つまり、キーの押下、ネットワークからのパケット、タイマーなど) には機能しません。
オブジェクトごとに 1 つのスレッド (C++11 以降)
これは、マルチスレッド環境における興味深いソリューションです。以前の解決策がどれも利用できない場合は、スレッドを使用して問題を解決できる場合があります。
C++11 には、という名前の新しい特殊指定子thread_local
があります。昔は、各スレッドの実装に固有のものを手作業で処理する必要がありました...今ではこれを行うだけです:
thread_local Class_w_callback * callback_context = nullptr;
次に、コールバックで、をクラスcallback_context
へのポインタとして使用できます。Class_w_callback
もちろん、これは、作成するオブジェクトごとに 1 つのスレッドを作成する必要があることを意味します。これは、ご使用の環境では実行できない場合があります。私の場合、すべて独自のループを実行しているコンポーネントがあるため、それぞれに独自のthread_local
環境があります。
ライブラリが自動的にイベントを生成する場合、おそらくそれもできないことに注意してください。
スレッドを使用した古い方法 (および C ソリューション)
前述したように、昔はローカル スレッド環境を自分で管理する必要がありました。pthread
(Linux ベース) を使用すると、次の方法でスレッド固有のデータにアクセスできますpthread_getspecific()
。
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);
これにより、動的に割り当てられたメモリが使用されます。これはおそらく、thread_local
Linux の g++ で が実装されている方法です。
MS-Windows では、おそらくTlsAlloc関数を使用するでしょう。