2013-09-26 61 views
1

我正在將C++庫橋接到iPhone應用程序。這工作正常。現在我爲從C++庫觸發的特定事件添加一個偵聽器(以lambda調用的形式),並且必須以某種方式冒泡到iPhone應用程序。將Objective-C塊傳遞給C++ lambda

我想過使用塊。當我實現監聽,它看起來是這樣的:

typedef void (^LISTENER)(NSString* param1, NSString* param2) ; 

-(void) setListener:(LISTENER) listener 
{ 
    cppDelegate->setListener([&listener](string p1, string p2) 
     { 
      @autoreleasepool { 
       NSString *param1 = [NSString stringWithUTF8String:p1.c_str()]; 
       NSString *param2 = [NSString stringWithUTF8String:p2.c_str()]; 
       listener(param1, param2); //This fails 
      } 
     } 
    ); 
} 

這是我如何設置監聽器:

listener = ^(NSString* param1, NSString* param2) //this is a MyObj member variable 
{ 
    @autoreleasepool { 
     NSLog(@"%@, %@", param1, param2); 
    } 
}; 

[myObj setLogFunction:listener]; 

我看到的問題是,在調用塊聽衆listener(param1, param2);失敗與EXC_BAD_ACCESS。當我進入這一行時使用調試器,它會轉到一些機器代碼並失敗。

我不確定發生了什麼事。就好像聽衆沒有被初始化。我所能想到的是,塊監聽器不能傳遞給C++ lambda,但我不知道如何解決這個問題。我傳遞一個void指針並將其返回,但這沒有任何區別。

回答

0

塊文字是在堆棧上創建的,並且如果以超出創建它們的上下文的方式使用它們,則必須將其複製。在大多數情況下,在Objective-C中使用塊但在C++中不使用塊時,這會自動完成。在我的代碼中,我通常在傳遞到C++之前通過在objective-c上執行[listener copy]來處理此問題,但在這種情況下,我認爲您可能只能通過值捕獲偵聽器,而不是通過lambda引用:只需更改[&listener][listener]

2

該問題與塊無關,而是因爲您通過引用(&)在lambda中捕獲listener。 C++中未定義的行爲是在局部變量作用域的持續時間之後使用對局部變量的引用(調用-setListener)。無論如何,從來沒有指向通過引用捕獲它,因爲你從來沒有分配到listener變量。

解決方案是通過值來取代它([listener](...)。