Call object C code from delphi

I am trying to do background fetching work in my firemonkey application.

I still realized that my perfromFetchWithCompletionHandler is called and is loading new information.

The problem occurs when I finished with my fetch and I need to call the finallyHandler code block, the application freezes and I don't get any exception (which I can read at least)

Setup:

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; 

execute the performFetchWithCompletionHandler man page

I tried with various declarations like a function pointer, but since it is not a function pointer, I think this will not work.

Any ideas?

Thanks Robert

+2
source share
2 answers

I found a solution that works: imp_implementationWithBlock

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

// Changed the handler for entering 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'; 

// Added links to imp_implementationWithBlock and imp_removeBlock from libobjc

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

// The declared IMP type as function c, 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; 
+2
source

This is what Apple calls " blocks ".

You can find a little more detailed technical information about them in the following Apple document: http://www.opensource.apple.com/source/libclosure/libclosure-53/BlockImplementation.txt

Unfortunately, for Delphi this is not so easy to implement. Thus, it might be the best choice for creating objective-c dylib, which in turn will take care of the block and use it from your Delphi application.

+1
source

All Articles