2008-11-11 18 views
21

.deote boost :: işlevi bir düz işlev işaretçisi (aynı imza) bekleyen bir yönteme artırmak için boost :: bind geçmek için düz bir işlev işaretçisi işlevi

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 *)' 

Ben benzer hatayı :: bir destek depolama işlevini önlemek ve sadece doğrudan bağlı functor geçmesine ama sonra alabilirim: Sana hedefi kullanmak istiyorum düşünüyorum

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

cevap

39

herkes accepted answer sadece önemsiz vakalarla çalıştığını fark etti mi? <> :: target() işlevinin tek yolu, C geri çağırma ile ilişkilendirilebilecek bir nesneyi döndürür; bu, C geri çağırma ile ilişkilendirilebilecek bir nesne ile yapılmışsa. Eğer durum buysa, o zaman doğrudan bağlanmış ve <> ile başlayan tüm işlevlerini atlamış olabilirsiniz.

Bunu düşünüyorsanız, bunun için sihirli bir çözüm yoktur. C stili bir geri arama, yürütülebilir koda işaret eden tek bir işaretçi olarak saklanır. Herhangi bir belirgin destek :: function <> en az iki işaretçiye ihtiyaç duyacaktır: biri çalıştırılabilir koda, diğeri de çağrıyı kurmak için gereken verilere (örneğin, 'bu' işaretçisine, bir üye üye durumunda fonksiyonu).

Yükseltme işlevini kullanmanın en doğru yolu :: function and boost :: C callbacks ile bağlama, geri arama imzasını karşılayan bir shim işlevi oluşturmaktır, hangi fonksiyonun çağrılacağını <> ve çağırır. Genellikle C geri çağrıları 'kullanıcı verileri' için bir çeşit boşluğa * sahip olacaktır; Eğer fonksiyon işaretçisi saklamak orası: Elbette

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

geri arama imza kullanıcı veri işaretçisi çeşit içermiyorsa,, şans bitti. Ancak, bir kullanıcı veri işaretçisi içermeyen herhangi bir geri arama, çoğu gerçek dünya senaryosunda halihazırda kullanılamaz durumda ve yeniden yazılması gerekiyor.

+1

'boost :: function pfn = static_cast > (userData) '' boost :: function * kullanmalı mı yoksa derleme hatası mı olacak? – Gohan

+0

@Gohan evet, yazarın amacı buydu. – Yann

11

() üye fonksiyonu boost :: fonksiyonunun

#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

bunu bağlama çalışabilirim (... ağız dolusu değil mi)? Güncelleştirme: Bir amaç, bir işlevi geri arama işlevine bağlamaktır. şimdi ne olacak?

+0

Bir araca onu bağlamadan bir geri çağırma elde etmenin tek yolu, ücretsiz bir nesne aracılığıyla –

3

can you get it working with bind?

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

Bu, by design dur. Temel olarak, bind tamamen farklı bir tür döndürdüğünden, bunun işe yaraması mümkün değildir. Temel olarak, bir bağlayıcı proxy nesnesi bir C işlev işaretçisine dönüştürülemez (çünkü bir değil: bir işlev nesnesidir). boost::bind tarafından döndürülen tür karmaşıktır. Mevcut C++ standardı, istediğiniz şeyi yapmanın iyi bir yolunu sağlar. C++ 0x böyle bir şey başarmak için buraya kullanılabilecek bir decltype ifadesi ile donatılmış olacak: bu ya çalışmayabilir diye

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

dikkat edin. Test etmenin hiçbir yolu yok.

+0

Tamam, amaç bir işlevi geri arama işlevine bağlamaktır. şimdi ne olacak? –

+0

Temel olarak yapamazsınız. Boost :: bind' ve 'boost :: function' kullanılmıyor.Tek olanak, gerekli işlevi sabit kodlamak ve ona bir işaretçi almak olabilir. –

+6

adam, python :( –

İlgili konular