2009-02-05 45 views
3

我需要將一個方法綁定到一個函數回調中,除非此代碼段不合法,如demote-boostfunction-to-a-plain-function-pointer中所述。來自綁定方法的原始函數指針

獲取此行爲的最簡單方法是什麼?

struct C { 
void m(int x) { 
    (void) x; 
    _asm int 3; 
}}; 

typedef void (*cb_t)(int); 
int main() { 
    C c; 
    boost::function<void (int x)> cb = boost::bind(&C::m, &c, _1); 
    cb_t raw_cb = *cb.target<cb_t>(); //null dereference 
    raw_cb(1); 
    return 0; 
} 

回答

2

你可以讓你自己的類和boost綁定函數做同樣的事情。所有類所要做的就是接受函數類型和指向包含該函數的對象的指針。例如,這是一個無效的回報和無效PARAM代表:

template<typename owner> 
class VoidDelegate : public IDelegate 
{ 
public: 
    VoidDelegate(void (owner::*aFunc)(void), owner* aOwner) 
    { 
     mFunction = aFunc; 
     mOwner = aOwner; 
    } 
    ~VoidDelegate(void) 
    {} 
    void Invoke(void) 
    { 
     if(mFunction != 0) 
     { 
     (mOwner->*mFunction)(); 
     } 
    } 

private: 
    void (owner::*mFunction)(void); 
    owner* mOwner; 
}; 

用法:現在

,因爲VoidDelegate<C>是一個類型,具有這些集合可能是不實際的,因爲什麼,如果該列表是否包含B類的函數呢?它不能。

這是多態性發揮作用的地方。你可以創建一個接口IDelegate,其中有一個函數調用:

class IDelegate 
{ 
    virtual ~IDelegate(void) { } 
    virtual void Invoke(void) = 0; 
} 

如果VoidDelegate<T>工具IDelegate你可以有IDelegates的集合,因此有回調,以在不同的類類型的方法。

2

要麼你可以推說綁定參數到一個全局變量,創建一個靜態函數,可以拿起值並調用它的函數,或者你將不得不在產生每個實例功能飛 - 這將涉及某種即時代碼生成一個存根函數堆上有一個靜態局部變量設置爲您想要的值,然後調用它的功能。

第一種方法簡單易懂,但根本不是線程安全的或可重入的。第二個版本是混亂和困難的,但是如果做得對,則是線程安全的和可重入的。

編輯:我剛剛發現,ATL使用代碼生成技術來做到這一點 - 它們會動態生成think,設置this指針和其他數據,然後跳轉到回調函數。 Here's a CodeProject article,它解釋了這是如何工作的,並可能讓你知道如何自己做。特別看最後一個樣本(程序77)。

請注意,由於文章寫了DEP已經存在,你需要使用VirtualAllocPAGE_EXECUTE_READWRITE來獲得一塊內存,你可以分配你的thunk並執行它們。

+0

動態代碼gen肯定太複雜。尋找儘可能簡單。 – 2009-02-05 15:55:17

+0

第一種方法是我所做的,看到我的回覆..就是你在說什麼? – 2009-02-05 15:55:50

+0

我想它會是,但是我想我無論如何都會把它扔出去。 – Eclipse 2009-02-05 16:09:35

0

我現在通過將C轉換爲單例,將C :: m分解爲C :: m_Impl,並聲明轉發給單例實例的靜態C :: m(int)。談談黑客。

1
#include <iostream> 
typedef void(*callback_t)(int); 

template< typename Class, void (Class::*Method_Pointer)(void) > 
void wrapper(int class_pointer) 
{ 
    Class * const self = (Class*)(void*)class_pointer; 
    (self->*Method_Pointer)(); 
} 

class A 
{ 
public: 
    int m_i; 
    void callback() 
    { std::cout << "callback: " << m_i << std::endl; } 
}; 

int main() 
{ 
    A a = { 10 }; 
    callback_t cb = &wrapper<A,&A::callback>; 
    cb((int)(void*)&a); 
} 
相關問題