2012-12-17 32 views
9

Tôi đang thực hiện một số Interop từ Mono C# tới Obj-C và chạy vào vấn đề này. Mã C# cần chuyển qua một cuộc gọi lại - mà nó thực hiện với một con trỏ hàm. Tôi có thể lấy con trỏ hàm từ phía Obj-C và gọi nó và mọi thứ hoạt động. Nhưng bây giờ tôi cần phải cung cấp cho con trỏ hàm đó như một cuộc gọi lại tới API của bên thứ ba hoạt động với các khối như một cuộc gọi lại. Tôi muốn bên thứ ba gọi hàm C# - vì vậy tôi đang cố chuyển đổi con trỏ hàm thành một khối để bên thứ ba có thể chạy hoặc tạo một loại cầu nối - tạo khối của riêng tôi chạy con trỏ hàm đó và đưa nó cho bên thứ ba. Tôi dường như không thể tìm cách để làm điều đó - làm thế nào tôi sẽ tạo ra một khối với thông tin của chức năng để chạy và sau đó cung cấp cho nó cho bên thứ ba. Có thể có một lựa chọn khác cho tôi?"Chuyển đổi" một con trỏ hàm thành một khối trong mục tiêu-C

Chỉnh sửa: Đặt hàm trong biến toàn cầu có thể hoạt động nhưng tôi muốn có thể có vô số những thứ như API của bên thứ ba không đồng bộ và tôi không muốn nó gọi sai gọi lại.

Mã tôi đã cố gắng:

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 

Và sau đó tôi chạy này với

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

Và nó không thành công với BAD_ACCESS. Có lẽ tôi đang làm một cái gì đó sai như tôi không phải là rất thành thạo với Obj-C được nêu ra. Tôi có thể xác nhận rằng cuộc gọi lại là ok nếu chạy trực tiếp và khối đó đang được gọi nhưng nó không thành công trên dòng hàm (kết quả).

Trả lời

6

tại sao không chỉ có một chức năng đơn giản

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

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

Vâng, bạn đã đúng. Vì lý do nào đó mà tôi không nghĩ về điều đó. Công trình lớn và rất sạch sẽ. Cảm ơn bạn! – Amitloaf

5

gì về

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

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

Sau đó myBlock là một khối mà nắm bắt được giá trị của con trỏ hàm và gọi hàm khi khối được thực thi.


thêm: Đề nghị của tôi, dựa trên mã của bạn, sử dụng một @property (và giả định rằng bạn biên dịch với 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

Biến toàn cầu? Điều đó không tốt lắm bởi vì sau đó tôi không thể một vài trong số đó.Tôi đã thử đặt myBlock như một thành viên trong một lớp cùng với myFunc nhưng khi tôi cố gắng chạy myFunc từ myBlock thì có lẽ nó không nằm trong phạm vi của nó và nó không thành công với BAD_ACCESS. Tôi đoán các biến toàn cầu sẽ là phương sách cuối cùng nhưng tôi muốn có cách tiếp cận phi toàn cầu – Amitloaf

+0

@Amitloaf: Tôi không muốn đề xuất biến toàn cầu. 'myFunc' có thể là bất kỳ con trỏ hàm nào. Giá trị được giữ trong khối khi khối được gán. –

+0

Tôi đã thêm một số thông tin khác về cách tôi đã thử triển khai một cái gì đó như những gì bạn đề xuất. Muốn suy nghĩ của bạn về cách giải quyết nó, cảm ơn! – Amitloaf

0

Một khối là dưới mui xe một con trỏ đến một cấu trúc dữ liệu địa phương. Một khối không hợp lệ ngay khi bạn rời khỏi phạm vi nơi nó được khai báo. Phạm vi là if-statement trong init; ngay khi bạn rời khỏi đó, khối không hợp lệ.

Bạn đang phá vỡ quy ước mã hóa ở đây theo cách không tốt. Đầu tiên, các biến mẫu sẽ bắt đầu bằng dấu gạch dưới, để mọi người nhìn thấy những gì bạn đang làm. Tốt hơn để sử dụng các thuộc tính mà không khai báo các biến mẫu. Và mọi thuộc tính khối phải được khai báo là "bản sao". Nếu bạn làm điều đó, mọi thứ đều ổn.

Các vấn đề liên quan