通过C ++中的非静态函数设置C函数指针的回调

时间:2015-03-01 09:42:56

标签: c++ c pointers function-pointers

感兴趣的C头(some_external_library.h)声明以下struct,包含一个函数指针:

#ifdef __cplusplus
extern "C" {
#endif
    typedef struct {
        void (*function_ptr)(void);
    } fp_test;
    /* ... */
#ifdef __cplusplus
}
#endif

some_external_library.c中发生一些有趣的事件时,会调用此函数指针。

我想在名为struct的C ++ class实例中设置指向此Foo实例的指针,然后设置function_ptr的值到Foo实例的非静态函数的地址。换句话说,我希望我的C ++代码定义这个函数指针的作用。

例如,这是一个类声明(foo.h):

class Foo {
    public:
        fp_test *fp_test_ptr;
        void setup(void);
        void breakdown(void);
        void my_callback(void);
};

有三个函数:一个用于初始化值的setup函数,一个用于释放任何指针或对象的breakdown函数,以及一个简单的my_callback函数,它接受并不返回任何参数。

这是类定义(foo.cpp):

int main(int argc, char** argv) {
    Foo some_foo;
    some_foo.setup();
    some_foo.breakdown();
    return EXIT_SUCCESS;
}

void Foo::setup(void) {
    fp_test_ptr = new fp_test;
    fp_test_ptr->function_ptr = &Foo::my_callback;
}

void Foo::breakdown(void) {
    delete fp_test_ptr;
}

void Foo::my_callback(void) {
    std::fprintf(stderr, "Callback called...\n");
}

编译时,我收到以下错误:

foo.h:: error: assigning to 'void (*)()' from incompatible type 'void (Foo::*)()'
fp_test_ptr->function_ptr = &Foo::my_callback;
                          ^------------------

我尝试转换此调用,但收到一条错误消息,指出我无法从void (Foo::*)()类型转换为void (*)()

如何在C ++中设置非静态方法作为C库的函数指针?

我能够获得static Foo::my_callback()版本的some_foo进行编译,但我不认为我可以使用静态方法来满足我的需求,因为我无法访问类实例{{1}}中的非全局成员的状态,仅为全局成员的值。

有没有办法用非静态函数做到这一点?

2 个答案:

答案 0 :(得分:2)

通常的方法是有两个函数:一个是静态函数,一个是成员函数,并将对象实例作为参数传递

class Foo {
public:
    fp_test *fp_test_ptr;
    void setup();
    void breakdown();
    void my_callback();
    static void _my_callback(void* self);
};

void Foo::_my_callback(void* self)
{
    reinterpret_cast<Foo*>(self)->my_callback();
}

将函数指针的C签名更改为

void (*function_ptr)(void*)

调用它时,将对象实例作为参数传递。

修改 要从C调用,大概你需要知道它所引用的对象,所以不知何故,你需要一个将C ++实例传递给C的方法。

Foo* fu1 = new Foo();
Foo* fu2 = new Foo();
/* fu1 and fu2 need to be passed to the C program */
...
/* Setting up */
fp_test pointerTest;
pointerTest.function_ptr = Foo::_my_callback;
...
/* Calling */
pointerTest.function_ptr(fu1);
pointerTest.function_ptr(fu2);

答案 1 :(得分:0)

这是不可能的。每个非静态的c ++成员函数都有一个隐藏的&#34; this *&#34;参数。所以函数签名总是不同的。