2014-03-13 61 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