2017-10-11 51 views
3

我想通过我的类方法作为参数传递给一个(第三方)功能 (听者 - 不能改变),它接受一个函数指针和一个void* 。以下是一个示例:绑定类的方法,并把它作为函数指针

#include <functional> 

typedef void(*pfnc) (void*); 

struct Foo 
{ 
    static void static_foo(void*) 
    { 
    } 

    void foo(void*) 
    { 
    } 

    void listner(pfnc f, void* p) 
    { 
     f(p); 
    } 

    void test() 
    { 
     listner(static_foo); // works with static method 

     auto f = [](void*) {}; 
     listner(f); // works with lambda 

     std::function<void(void*)> stdf = std::bind(&Foo::foo, this, std::placeholders::_1); 
     listner(stdf); // does not compile with not static method 
    } 
}; 

不幸的是,我的解决方案不能编译。我需要改变什么?

+1

函数指针没有状态。你将不得不使用'void *'参数。从另一方面来说,这个参数是存在的,与我遇到的其他一些特定的C API不同。 – chris

+1

你确定'listener'方法只接受'pfnc'吗?通常这样的方法接受用户指定的'void *'参数,该参数在回调处理器方法期间传递... –

+0

我通常使用一个lambda来捕获此方法来调用该方法。 –

回答

1

从回调信号的外观来看,监听器API将一个指针作为“用户定义数据”作为无效指针。您可以通过this的数据和一个小的无状态代理功能路由到处理器上Foo

typedef void(*pfnc) (void*); 

struct Foo 
{ 
    static void static_foo(void*) 
    { 
    } 

    void foo() 
    { 
    } 

    void listner(pfnc f, void* user_data) 
    { 

     // eventually calls 
     f(user_data); 
    } 

    void test() 
    { 
     listner(static_foo, nullptr); // works with static method 

     auto f = [](void*) { 
     }; 
     listner(f, nullptr); // works with lambda 

     listner([](void* pv) 
     { 
      reinterpret_cast<Foo*>(pv)->foo(); 
     }, this); 
    } 

}; 
0

对于这个问题的例子有可能通过成员函数指针。但是,必须知道该成员被调用的实例。如果调用函数也是成员函数,那么我们可以使用this来调用通过指针传递的成员函数。

struct Foo 
{ 
    static void static_foo(void*) 
    { 
    } 

    void foo(void*) 
    { 
    } 

    void listner(pfnc f) 
    { 
    } 

    void listner(void(Foo::*f)(void*)) 
    { 
     (this->*f)(nullptr); // call member function pointer for this 
    } 

    void test() 
    { 
     listner(static_foo); // works with static method 

     auto f = [](void*) {}; 
     listner(f); // works with lambda 

     listner(&Foo::foo); // pass pointer to member function 
    } 
}; 
0

你们的榜样“作品”与静态成员函数,因为这几乎等同于普通的旧功能

它还“作品”与您提供的拉姆达,因为它是一个捕获少拉姆达它可以被转换为函数指针(参见Passing lambda as function pointer) 然而,它不适用于具有捕获的lambda表达式,因为如chris所述,函数指针没有状态,即没有地方存储将捕获的内容。

这同样适用于绑定。您可以将它存储在std :: function中,因为这样的对象有一个状态,但不能将它存储在普通(无状态)函数指针中。

如果你不相信,看看什么stdf.target_type()告诉你,并与typeid(static_foo).name() 你也可以看看返回类型的std ::的绑定

在年底比较,如其他已经说过,你将不得不在用户数据中展开你的对象,也就是void *。 这可能是值得研究的是否可以将它包装在以std :: function作为参数的帮助函数中...

相关问题