Функция-член класса в качестве обратного вызова с использованием boost :: bind и boost :: function - PullRequest
7 голосов
/ 04 января 2010

Я работаю над настройкой функции-члена в качестве обратного вызова для C-библиотеки, которую я использую. C-библиотека устанавливает обратные вызовы следующим образом:

typedef int (*functionPointer_t)(myType1_t*, myType2_t*, myType3_t*);

setCallback(param1, param2, functionPointer, param4)

Я бы хотел использовать boost :: bind (если это возможно) для передачи указателя на функцию. Я бы предпочел, чтобы указанная функция была членом экземпляра класса, а не статическим членом. Э.Г.

Class A {
 public: 
  A();
 protected:
  int myCallback(myType1_t*, myType2_t*, myType3_t*); //aka functionPointer_t
}

Можно ли это сделать с помощью boost :: bind и boost :: function? На Как я могу передать функцию-член класса в качестве обратного вызова? (3-й ответ) кажется, что я мог бы объявить следующее (где-нибудь, или как typedef):

boost::function<int (A*, myType1_t*, myType2_t*, myType3*> myCallbackFunction

И затем где-нибудь в A (ctor) вызову boost :: bind для этого типа и передать его в вызов C-библиотеки.

Это возможно, или я с базы? Большое спасибо.

Ответы [ 3 ]

5 голосов
/ 04 января 2010

Нет. Типы функторов, такие как boost::function, не преобразуются в указатели на функции для использования с механизмами обратного вызова C.

Однако большинство механизмов обратного вызова C имеют какой-то механизм токенов, поэтому ваша функция обратного вызова (которая является статической) имеет некоторую контекстную информацию. Вы можете использовать это, чтобы написать класс-обертку, который отображает эти токены на объекты функтора и передает выполнение правильному:

class CallbackManager {
public:
    typedef boost::function<int (type1*, type2*, type3*)> callback;

    static void setCallback(CallbackManager::callback cb)
    {
        void *token = ::setCallback(staticCallback);
        callbacks[token] = callback_I;
    }

    static void staticCallback(void* token, type1* a, type2* b, type3* c)
    { return mcallbacks[token](a, b, c); }

private:
    static std::map<void*, callback > callbacks;
};
1 голос
/ 04 февраля 2011

не использует map, это дает время выполнения и загромождает код статической картой.

используйте reinterpret_cast вместо.

например

// clib.h
typedef void (*CALLBACK_FUNC)(int code,void *param);

void set_callback( CALLBACK_FUNC, void * param ); 

// a.h

class A {
public:
    A()
    {
        ::set_callback( &A::static_callback, this);
    }
private:
    static void static_callback(int code, void * param)
    { 
        A* self = reinterpret_cast<A*>(param);
        self->callback( code );
    }

    inline void callback( int code )
    {
        // write you code here.
    }
};
0 голосов
/ 04 января 2010

Проблема с функциями-членами заключается в том, что они автоматически получают указатель на экземпляр объекта в качестве первого параметра - указатель «this». Вот почему вы не можете использовать функции-члены с функциями обратного вызова C. Вы должны иметь объект И указатель на функцию вместе, чтобы использовать функцию-член.

...