2008-11-11 81 views
21

想要將boost :: bind傳遞給期望普通函數指針(相同簽名)的方法。將boost :: function降級爲普通函數指針

typedef void TriggerProc_type(Variable*,void*); 
void InitVariable(TriggerProc_type *proc); 
boost::function<void (Variable*, void*)> triggerProc ... 
InitVariable(triggerProc); 

error C2664: 'InitVariable' : cannot convert parameter 1 from 
'boost::function<Signature>' to 'void (__cdecl *)(type *,void *)' 

我可以避免存儲一個boost ::功能,只需直接通過綁定仿函數,但後來我得到類似的錯誤:

error C2664: 'blah(void (__cdecl *)(type *,void *))' : cannot convert parameter 
1 from 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(type *,void *)' 

回答

39

有沒有人注意到accepted answer只有微不足道的情況下工作?功能<> :: target()的唯一方法是返回一個可以綁定到C回調的對象,如果它是用可以綁定到C回調的對象構造的話。如果是這樣的話,那麼你可以直接綁定它,並跳過所有的功能開始。

如果你仔細想想,這裏沒有任何魔法解決方案。一個C風格的回調被存儲爲指向可執行代碼的單個指針。任何不重要的boost :: function函數都需要至少兩個指針:一個指向可執行代碼,另一個指向創建調用所需的數據(例如,'this'指針,在綁定成員的情況下功能)。

使用boost :: function和使用C回調的boost :: bind的正確方法是創建一個滿足回調簽名的填充函數,計算出調用哪個函數<>並調用它。通常C回調對於'用戶數據'會有一些void *;這就是你藏匿的函數指針:

typedef void (*CallbackType)(int x, void* user_data); 
void RegisterCallback(CallbackType cb, void* user_data); 

void MyCallback(int x, void* userData) { 
    boost::function<void(int)> pfn = static_cast<boost::function<void(int)> >(userData); 
    pfn(x); 
} 

boost::function<void(int)> fn = boost::bind(myFunction(5)); 
RegisterCallback(MyCallback, &fn); 

當然,如果你的回調簽名不包括某種類型的用戶數據指針,你的運氣了。但是,任何不包含用戶數據指針的回調在大多數真實世界的場景中已經不可用,並且需要重寫。

11

我想你要使用的目標()成員函數boost :: function(不是那麼一口......)

#include <boost/function.hpp> 
#include <iostream> 

int f(int x) 
{ 
    return x + x; 
} 

typedef int (*pointer_to_func)(int); 

int 
main() 
{ 
    boost::function<int(int x)> g(f); 

    if(*g.target<pointer_to_func>() == f) { 
    std::cout << "g contains f" << std::endl; 
    } else { 
    std::cout << "g does not contain f" << std::endl; 
    } 

    return 0; 
} 
0

你可以使用bind嗎?

#include <boost/function.hpp> 
#include <boost/bind.hpp> 

void f(int x) 
{ 
    (void) x; 
    _asm int 3; 
} 

typedef void (*cb_t)(int); 

int main() 
{ 
    boost::function<void (int x)> g = boost::bind(f, 3); 
    cb_t cb = *g.target<cb_t>(); //target returns null 
    cb(1); 

    return 0; 
} 

更新:好的,以及意圖是將一個方法綁定到一個函數回調。那麼現在怎麼辦?

+0

將數據放入回調而不綁定到回調函數的唯一方法是通過一個免費對象 – 2009-02-05 04:29:21

3

can you get it working with bind?

cb_t cb = *g.target<cb_t>(); //target returns null 

這是by design。基本上,因爲bind返回一個完全不同的類型,所以這是行不通的。基本上,綁定器代理對象不能轉換爲C函數指針(因爲它不是一個:它是一個函數對象)。 boost::bind返回的類型很複雜。目前的C++標準沒有任何好的方法來做你想做的事情。的C++ 0x將配備一個decltype表達式,在這裏可以用來實現這樣的事情:

typedef decltype(bind(f, 3)) bind_t; 
bind_t target = *g.target<bind_t>(); 

注意,這可能會或可能無法正常工作。我沒有辦法測試它。

+0

好吧,其目的是將方法綁定到函數回調中。那麼現在怎麼辦? – 2009-02-04 17:04:30

+0

基本上,你不能。不使用`boost :: bind`和`boost :: function`。唯一的手段可能是硬編碼所需的功能並檢索指向它的指針。 – 2009-02-04 17:31:57