3

将来のある時点で呼び出されるコールバック (関数ポインタ) を引数として受け入れるライブラリ関数 (変更できない) があるとします。私の質問: コールバックが呼び出されたときに余分なデータを取得できるように、関数ポインターと共に余分なデータを格納する方法はありますか? プログラムはcです。

例えば:

// callback's type, no argument
typedef void (*callback_t)();  

// the library function            
void regist_callback(callback_t cb);       

// store data with the function pointer
callback_t store_data(callback_t cb, int data);

// retrieve data within the callback
int retrieve_data();

void my_callback() {
    int a;
    a = retrieve_data();
    // do something with a ...
}

int my_func(...) {
    // some variables that i want to pass to my_callback
    int a;

    // ... regist_callback may be called multiple times
    regist_callback(store_data(my_callback, a));
    // ...
}

問題は、callback_tが引数を受け入れないためです。私の考えは、regist_callback に入力するたびに小さな asm コードを生成することです。それが呼び出されると、実際のコールバックとそのデータを見つけてスタック (または未使用のレジスタ) に格納し、実際のコードにジャンプします。コールバック内で、データを見つけることができます。

疑似コード:

typedef struct {
    // some asm code knows the following is the real callback
    char trampoline_code[X]; 
    callback_t real_callback;
    int data;       
} func_ptr_t;

callback_t store_data(callback_t cb, int data) {
    // ... malloc a func_ptr_t
    func_ptr_t * fpt = malloc(...);

    // fill the trampoline_code, different machine and
    // different calling conversion are different
    // ...

    fpt->real_callback = cb;
    fpt->data = data;

    return (callback_t)fpt;
}

int retrieve_data() {
    // ... some asm code to retrive data on stack (or some register)
    // and return
}

それは合理的ですか?そのような問題に対して行われた以前の作業はありますか?

4

1 に答える 1