2017-04-06 40 views
-1

我有一個特殊的回調(這是在一些'C'土地定義)需要填充一些額外的工作,不屬於回調函數的一部分。它是這樣的......std ::綁定一個常規函數,但結尾

typedef void (*callback_func)(int); 
extern int set_callback(callback_func cb); 

在我的C++代碼,我需要SET_VALUE是回調的範圍之外定義,在我的課的承諾。所以,我必須捕獲std :: promise成員變量或這個併發送到回調函數,然後在調用回調函數後設置它,只是編譯器不喜歡它。我這樣做,這樣一來,

set_callback([this](int x) { 
    // some code ... 
    prom.set_value(true); 
}); 

下面是剪斷錯誤:

error: no matching function for call to 'set_callback' 
     set_callback([this](int var) { 
     ^~~~~~~~~~~~~~~~~~~~~~~~~ 
note: candidate function not viable: no known conversion from '(lambda at xxx ' to 'callback_func' 
      (aka 'void (*)(int)') for 1st argument 

我意識到,我需要以某種方式「綁定」的定時功能,使回調函數的std ::功能,但我不確定如何實現這一點 - 更不用說將它發送給參數並執行結尾語。請建議,謝謝!

回答

0

如果捕獲列表爲空,Lambdas只能衰減到函數指針。這是因爲代碼

[this](int x) { 
    // some code ... 
    prom.set_value(true); 
} 

大致相當於

struct SomeLambdaName { 
    MyCapture self; 

    auto operator()(int x) const { 
     // some code ... 
     self.prom.set_value(true); 
    } 
}; 

在另一方面,函數指針只是:指針。指向要調用的函數地址的指針。

在C++中,成員函數:

struct MyClass { 
    int i; 
    int add_x(int x) { return i = i + x; } 
}; 

大致是這樣的C代碼(取決於實現方式):

int add_x(MyClass *self, int x) { return self->i = self->i + x; } 

如果C代碼可以被改變採取void *要保存任意數據,可以這樣做:

typedef void (*callback_func)(int, void * data); 
extern int set_callback(callback_func cb); 
set_callback([](int x, void * data) { 
    MyClass &self = *reinterpret_cast<MyClass *>(data); 
    // some code ... 
    self.prom.set_value(true); 
}); 

否則,你必須有靜態對象或類似的東西。

+0

不幸的是,C代碼無法更改!爲了迴應你提出的建議,你建議把這個指針作爲一個void *傳遞給它(並且將它作爲第一個參數傳遞進來會更加一致 - 實質上,這就是這個指針是),但我相信有一個更好的方法將C函數綁定到std :: function,然後跟隨結尾,但我不知道如何。 – chimp45

+0

@ chimp45正如我所說的,將C函數綁定到'std :: function'是**不可能**。 – Justin

+0

@ chimp45函數指針包含調用約定,「C」或「C++」和說明符的定義。指向C++函數的指針與C不兼容,而不使用extern「C」。這也是它們不能被綁定爲C指針的原因。其次,除非類是一個微不足道的和POD,否則不能將「this」傳遞給C。您需要在C++代碼中創建n外部「C」函數,以便在其中進行適當的工作 – Swift