Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
409 views
in Technique[技术] by (71.8m points)

c++ - Passing a qualified non-static member function as a function pointer

I have a function in an external library that I cannot change with the following signature:

void registerResizeCallback(void (*)(int, int))

I want to pass in a member function as the callback, as my callback needs to modify instance variables.

Obviously this isn't possible with a simple:

registerResizeCallback(&Window::Resize);

so I'm not really sure how to solve the problem.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As Igor Oks indicates, you can't do this. The remainder of this question is not so much an answer to your problem, but a discussion of how something like this should work with a properly designed callback API (it appears the one you're using isn't).

Most well-designed callback interfaces let you provide a "void *" or some other way to get a context in the callback. A common way to use this with C++ is to pass an object pointer in the void * context parameter, then the callback function can cast it back into an object pointer and call the member method to do the real work. It's too bad the callback API you're using doesn't provide for context data.

Strictly speaking, the callback must be extern "C", but using static member methods for callbacks is common and I think in practice there's never a problem. (This is assuming that the callback API is a C interface, which is by far the most common).

An example:

// callback API declaration's

extern "C" {
    typedef unsigned int callback_handle_t;

    typedef void (*callback_fcn_t)( void* context, int data1, int data2);

    callback_handle_t RegisterCallback( callback_fcn_t, void* context);
    void UnregisterCallback( callback_handle_t);
}

// ----------------------------------

// prototype for wrapper function that will receive the callback and 
//  transform it into a method call

extern "C" 
static void doWorkWrapper( void* context, int data1, int data2);


// the class that does the real work

class worker {
public:
    worker() {
        hCallback = RegisterCallback( doWorkWrapper, this);
    }

    ~worker() {
        UnregisterCallback( hCallback);
    }

    void doWork( int data1, int data2) {
        // ... 
    };

private:
    callback_handle_t hCallback;
};

// the wrapper that transforms the callback into a method call
extern "C" 
static void doWorkWrapper( void* context, int data1, int data2)
{
    worker* pWorker = static_cast<worker*>( context);

    pWorker->doWork( data1, data2);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...