2012-12-17 19 views
9

我正在做一些從Mono C#到Obj-C的Interop並遇到此問題。 C#代碼需要傳遞一個回調 - 它使用一個函數指針。 我可以從Obj-C端獲取函數指針並調用它,並且一切正常。 但我現在需要給該函數指針作爲第三方API的回調函數,它與塊一起作爲回調函數使用。 我希望第三方調用C#函數 - 所以通過某種方式,我試圖將函數指針轉換爲塊,以便第三方可以運行它,或者創建某種橋樑 - 創建我自己的塊運行該函數指針並將其提供給第三方。我似乎無法找到辦法做到這一點 - 我將如何生成一個信息塊運行哪個函數,然後將其提供給第三方。 也許對我來說還有另一種選擇?將函數指針「轉換」爲目標中的某個塊-I

編輯:把功能在一個全局變量可能的工作,但我希望能有這些作爲第三方API的許多是異步的,我不希望它調用了錯誤的回調。

代碼我想:

typedef void (*DummyAction)(char * result); 
typedef void (^DummyBlock)(char * result); 

@interface FunctionToBlock : NSObject 
{ 
    DummyAction function; 
    DummyBlock block; 
} 

- (id) initWithFunction: (DummyAction) func; 
- (DummyBlock) block; 
@end 

@implementation FunctionToBlock : NSObject 
- (id) initWithFunction: (DummyAction) func { 
    if (self = [super init]) { 
     function = func; 
     block = ^(char * result) { 
      function(result); 
     }; 
    } 
    return self; 
} 

- (DummyBlock) block { 
    return block; 
} 
@end 

然後我跑這跟

void RegisterCallback(char * text, DummyAction callback) 
{ 
    FunctionToBlock *funcToBlock = [[FunctionToBlock alloc] initWithFunction : callback]; 
    funcToBlock.block(text); 
} 

它失敗BAD_ACCESS。也許我做錯了,因爲我還不是很熟練使用Obj-C。如果直接運行,並且該塊正在被調用,但是它在函數(結果)行上失敗,我可以確認該回調是否正常。

回答

6

爲什麼不只是有一個簡單的函數

typedef void (*DummyAction)(char * result); 
typedef void (^DummyBlock)(char * result); 

DummyBlock functionToBlock(DummyAction func) { 
    return [[^(char * result) { 
       func(result); 
      } copy] autorelease]; 
} 
+1

那麼,你是對的。出於某種原因,我沒有想到這一點。工程很好,很乾淨。謝謝! – Amitloaf

5

void (*myFunc)(int x); // ... your function pointer 

void (^myBlock)(int) = ^(int x) { 
    myFunc(x); 
}; 

然後myBlock是什麼,其捕獲函數指針的值,並執行該塊時調用該函數的塊。


新增:我的建議,根據你的代碼,使用@property(並假設你有ARC編譯):

FunctionToBlock.h:

typedef void (*DummyAction)(char * result); 
typedef void (^DummyBlock)(char * result); 

@interface FunctionToBlock : NSObject 
{ 
    DummyAction function; // Not really needed. 
} 

- (id) initWithFunction: (DummyAction) func; 
@property(copy, nonatomic) DummyBlock block; // "copy" is important here! 

@end 

FunctionToBlock.m:

#import "FunctionToBlock.h" 

@implementation FunctionToBlock : NSObject 
@synthesize block = _block; // Can be ommitted if you use Xcode 4.4 or later. 

- (id) initWithFunction: (DummyAction) func 
{ 
    if (self = [super init]) { 
     function = func; // Not really needed. 
     self.block = ^(char * result) { 
      func(result); // Use "func", not "self->function", to avoid retain cycle. 
     }; 
    } 
    return self; 
} 
+0

全局變量?這不是很好,因爲那樣我就沒有其中的幾個。我嘗試將myBlock作爲myFunc的成員放入類中,但是當我嘗試從myBlock運行myFunc時,它可能不在其範圍內,並且會因BAD_ACCESS而失敗。我猜全局變量將是最後的手段,但我更喜歡非全局方法 – Amitloaf

+0

@Amitloaf:我不想建議一個全局變量。 'myFunc'可以是任何函數指針。該值在塊被分配時在塊中捕獲。 –

+0

我添加了一些關於如何嘗試實現類似於您的建議的信息。想知道如何解決這個問題,謝謝! – Amitloaf

0

A嵌段是罩的指針到一個本地數據結構之下。一旦您離開聲明的範圍,塊就會失效。範圍是init中的if語句;只要你離開,該塊是無效的。

您在這裏打破編碼約定在一個糟糕的方式。首先,實例變量應該以下劃線開頭,這樣每個人都能看到你在做什麼。最好不要聲明實例變量而使用屬性。並且每個塊屬性都應該聲明爲「複製」。如果你這樣做,一切都很好。