从delphi调用目标C代码块 [英] Calling objective C code block from delphi

查看:143
本文介绍了从delphi调用目标C代码块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的firemonkey应用程序中执行后台获取.

I'm trying to make background fetch work in my firemonkey application.

到目前为止,我的perfromFetchWithCompletionHandler被调用并下载新信息.

I've gotten so far that my perfromFetchWithCompletionHandler gets called and downloads new information.

问题是当我完成提取操作并需要调用completionHandler代码块时,应用程序挂起并且没有任何异常(至少可以读取)

The problem comes when I'm done with my fetch and need to call the completionHandler code block, the app hangs and I don't get any exception (that I can read at least)

设置:

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;

我尝试过使用函数指针类型的不同声明,但是由于它并不是函数指针,我想这就是它不起作用的原因.

I've tried with different declarations of the function pointer type, but as it isn't a function pointer exactly I guess that's why it won't work.

有什么想法吗?

谢谢 罗伯特

推荐答案

我找到了一个可行的解决方案:

I've found a solution that works: imp_implementationWithBlock

procedure performFetchWithCompletionHandler(self : id; _cmd : SEL; application:    PUIApplication; handler : id );

///将处理程序更改为键入id(指针)

//Changed the handler to type id (Pointer)

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的引用

//Added references to imp_implementationWithBlock and imp_removeBlock from libobjc

type  IMP = function( self : id; cmd : SEL; Param1 : NSUInteger ) : id; cdecl;

///在这种情况下,使用一个NSUInteger参数将IMP声明为c函数,该函数对应于imp_implementationWithBlock返回的函数指针.

//Declared type IMP as a c function corresponding to the function pointer returned by imp_implementationWithBlock in this particular case with one NSUInteger parameter.

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;

这篇关于从delphi调用目标C代码块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆