【问题标题】:Setting up callback to C function pointer via non-static function in C++通过 C++ 中的非静态函数设置对 C 函数指针的回调
【发布时间】:2015-03-01 09:42:55
【问题描述】:

一个感兴趣的 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 中发生一些有趣的事件时,会调用此函数指针。

我想在一个名为Foo的C++class的实例中设置一个指向这个struct实例的指针,然后将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 库的函数指针?

我能够获得Foo::my_callback()static 版本来编译,但我认为我不能使用静态方法来满足我的需要,因为我无法访问非全局成员的状态在类实例some_foo中,只有全局成员的值。

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

【问题讨论】:

  • 除非您使用代理,否则它必须是静态的。 C ++就是那样愚蠢。这是由于名称修改造成的。

标签: c++ c pointers function-pointers


【解决方案1】:

解决这个问题的正常方法是使用两个 one 函数:一个静态函数和一个成员函数,并将对象实例作为参数传递

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);

【讨论】:

  • 您能否澄清一下我如何从 C 库方面调用静态 Foo::_my_callback(void *)?我不确定这是否可行,因为我必须从某个地方获取self,而 C 库将无法知道我从中调用它的对象。它所知道的只是在某些事件发生时调用函数指针,这应该触发 C++ 代码中的函数。
【解决方案2】:

这是不可能的。每个非静态 C++ 成员函数都有一个隐藏的“this *”参数。所以函数签名总是不同的。

【讨论】:

    猜你喜欢
    • 2011-12-22
    • 2020-06-28
    • 2011-11-21
    • 2012-05-05
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多