从delphi调用目标C代码块
我正在尝试在我的firemonkey应用程序中进行后台提取工作。
到目前为止,我已经调用了perfromFetchWithCompletionHandler并下载了新信息。
当我完成我的fetch并需要调用completionHandler代码块,应用程序挂起并且我没有得到任何exception(我至少可以阅读)时出现问题
建立:
TBackgroundFetchResultHandlerC = procedure ( AResult : NSUInteger ); cdecl; .. .. procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : TBackgroundFetchResultHandlerC ); .. .. objc_msgSend((UIApp as ILocalObject).GetObjectId, sel_getUid('setMinimumBackgroundFetchInterval:'), Interval); class_addMethod( objc_getClass('DelphiAppDelegate') , sel_getUid('application:performFetchWithCompletionHandler:'), @performFetchWithCompletionHandler, 'v@:@?' ); .. .. procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : TBackgroundFetchResultHandlerC ); var t : TThread; begin NSLog3('performFetchWithCompletionHandler:begin'); Handler(0); <<--Stops here //Next line of code never gets called. NSLog3(Format('performFetchWithCompletionHandler:done, done',[ FetchResult ]) ); end;
performFetchWithCompletionHandler手册页
我已尝试使用函数指针类型的不同声明,但由于它不是一个函数指针,我猜这就是为什么它不起作用。
有任何想法吗?
谢谢罗伯特
我找到了一个有效的解决方案: imp_implementationWithBlock
procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : id );
//将处理程序更改为类型id(指针)
const libobjc = '/usr/lib/libobjc.dylib'; {$IF NOT DECLARED(_PU)} const {$IFDEF UNDERSCOREIMPORTNAME} _PU = '_'; {$ELSE} _PU = ''; {$ENDIF} {$EXTERNALSYM _PU} {$ENDIF} function imp_implementationWithBlock( block :id ) : IMP; cdecl; external libobjc name _PU + 'imp_implementationWithBlock'; function imp_removeBlock( anImp : IMP ) : integer; cdecl; external libobjc name _PU + 'imp_removeBlock';
//从libobjc添加了对imp_implementationWithBlock和imp_removeBlock的引用
type IMP = function( self : id; cmd : SEL; Param1 : NSUInteger ) : id; cdecl;
//声明类型IMP为ac函数,对应于imp_implementationWithBlock在此特定情况下使用一个NSUInteger参数返回的函数指针。
procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application: PUIApplication; handler : id ); var ahandlerimp : IMP; begin .... //Code to perform fetch ahandlerimp := imp_implementationWithBlock( handler ); //Create c function for block ahandlerimp(self,_cmd,FetchResult ); //Call c function, _cmd is ignored imp_removeBlock(ahandlerimp); //Remove the c function created two lines up end;
这就是Apple所说的“ 块 ”。
您可以在Apple的以下文档中找到有关它们的更多技术细节: http : //www.opensource.apple.com/source/libclosure/libclosure-53/BlockImplementation.txt
不幸的是,从Delphi实现它似乎并不容易。 因此,创建一个objective-c dylib可能是一个更好的选择,它将依次处理块并使用Delphi应用程序中的块。