2008-11-11 4 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 *)' 

내가 유사한 오류 :: 후원을 저장하는 기능을 방지하고 단지 직접 결합 펑을 통과하지만 내가 얻을 수 있습니다 : 당신이 대상을 사용하려는 생각

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'포인터). 기능).

C 콜백과 함께 boost :: function과 boost :: bind를 사용하는 올바른 방법은 콜백 서명을 충족시키고 어떤 함수 <>을 호출하여 호출 하는지를 결정하는 것입니다. 일반적으로 C 콜백에는 '사용자 데이터'에 대한 무효 *가 있습니다. 당신이 당신의 함수 포인터를 숨겨 놓은 곳이있다 : 물론

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

을 콜백 서명이 사용자 데이터 포인터의 어떤 종류를 포함하지 않는 경우, 당신은 운입니다. 그러나 사용자 데이터 포인터를 포함하지 않는 콜백은 대부분의 실제 시나리오에서 이미 사용할 수 없으므로 다시 작성해야합니다.

+1

'boost :: function pfn = static_cast > (userData); '대신 boost :: function *을 사용해야합니다. 그렇지 않으면 컴파일 오류가 발생합니다. – Gohan

+0

@Gohan 예, 작성자의 의도였습니다. 게시물을 수정합니다. – Yann

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

바인드를 사용할 수 있습니까?

#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

데이터를 바인딩하지 않고 콜백에 가져 오는 유일한 방법은 무료 객체를 사용하는 것입니다. –

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

그래, 의도는 메소드를 함수 콜백에 바인딩하는 것입니다. 그래서 지금 뭐야? –

+0

기본적으로, 당신은 할 수 없습니다. 'boost :: bind'와'boost :: function'을 사용하지 않습니다.유일한 방법은 필요한 함수를 하드 코딩하고 포인터를 검색하는 것입니다. –

+6

남자, 이것은 파이썬에서 10 초 걸렸을 것이다 : ( –