2014-03-13 59 views
0

我必须使用C库来抓取图像,它具有流功能。所以当调用start_stream方法时,我必须传递一个函数指针。我想从一个类传递一个方法到那个函数。C回调和标准::函数::目标

这里是回调方法的签名:void StreamCallback(SomeType* img) ,我必须通过void(* StreamCallbackPtr)(SomeType* img)start_stream方法,其特征是int start_stream(StreamCallbackPtr stream_callback)

我有一个类,看起来像这样:

class MyClass 
{ 
private: 
    void Callback(SomeType* img) 
    { 
     std::cout << "grabbed" << std::endl; 
     // Do something with the image ... 
    } 

public: 
    void StartStream() 
    { 
     std::function<void(SomeType* img)> cb = 
      std::bind(&MyClass::Callback, this, std::placeholders::_1); 

     if(not cb) // if the call-wrapper has wrapped a callable object 
     { 
      std::cout << "error" << std::endl; 
      exit(0); 
     } 

     ptr_fun_ = cb.target<FuncType*>(); 

     if(ptr_fun_ != nullptr) 
     { 
      start_stream(ptr_fun_); 
     } 
     else 
     { 
      std::cout << "error" << std::endl; 
      exit(0); 
     } 
    } 

private: 
    typedef void FuncType(SomeType* img); 
    FuncType* ptr_fun_; 
}; 

但不幸的是ptr_fun_始终为空。你能发现错误吗?

+1

该代码不支持您传递C函数的目标。为获得最佳指导,请提供'start_stream'函数的完整签名。 –

回答

4
  • 您可以使用静态extern "C"函数。对于大多数平台,您还可以使用static成员函数,但是在形式上它不需要与C兼容,也不能声明为extern "C"。我认为这是在Solaris上,必须禁用相关的警告。

  • 您不能使用std::function,因为它不是C函数:它是一个C++对象,它具有operator()成员函数,一个仿函数。类似地,bind的结果和捕获任何东西的lambda(特别是捕获指针的ldada)的结果类似。

  • 特定于平台的功能可用于实现动态创建的C函数,但这就像使用洲际H-bomb导弹射击gnat(单数)。

所以总之,去静态extern "C"功能。

它可以使用静态变量转发到某个对象的成员函数,如果你想要的话。在回调接收到客户端代码提供的数据指针参数的情况下,您可以将其用作this-指针。但是,如果你想转发一个对象的成员函数,给定签名int start_stream(StreamCallbackPtr stream_callback),你只需要使用一些静态变量。

+0

感谢您的答案,静态变量是我已经使用。最大的限制是,如果我想要多个MyClass实例,我必须添加一个静态变量,以重定向来自不同流的图像。有人告诉我,我在问题中写的解决方案可行,但我必须确定它不会。 – Athanase