2017-10-11 64 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作爲參數的幫助函數中...