Pyobjus framework integration held back by lack of objc block style callback integration

61 views
Skip to first unread message

Kevin Russell

unread,
Jan 31, 2017, 9:27:36 PM1/31/17
to Kivy users support
I've noticed that its quite common in objective C to handle callbacks with block integration which there isn't a strategy yet for in pyobjus (however works in pyobjc).
After alot of googling / coffee/ and attempts I've pretty much exausted all possibilities to get the following to work. I'm pretty motivated to solve this as it would open alot of doors in to iOS. 


Lets say you want to authorize the health kit to read write data with an objective c call... notice the completion:^ block.

[healthStore requestAuthorizationToShareTypes:shareObjectTypes readTypes:readObjectTypes completion:^(BOOL success, NSError *error) {//Nice Fat Block O Code}];

Ok so what can you do about this??

Of the things i've tried were to pass it a raw function, which fails due to an ffi encoding error. You could autoclass you own custom class that contains a block and then pass the block as the argument, but on the python getattr on the block the code will fail. 

Here's the custom class I was using
//Blocks.h

@interface HealthAuthResult: NSObject {

}

@property BOOL issuccess;

@property BOOL didtry;

-(void) healthAuthCallbackResult:(BOOL)success andError:(NSError *) error;

//@property (nonatomic,retain) void (^healthAuthBlock)(BOOL, NSError *);
//void (^healthAuthBlock)(BOOL, NSError *);

@end


//////////////
#import "Blocks.h"

@implementation HealthAuthResult

-(void) healthAuthCallbackResult:(BOOL)success andError:(NSError *) error
{
    self.didtry = YES;
    if(success == YES)
    {
        self.issuccess = YES;
    }
    else
    {
        self.issuccess = NO;
    }
}

//-(void) configureBlock{
//    self.healthAuthBlock = ^(BOOL success, NSError *error){
//        //[self healthAuthCallbackResult:success andError:error];
//        NSLog(@"Hello This is block");
//    };
//}

void (^healthAuthBlock)(BOOL, NSError *);

@end

Any attempt to access HealthAuthResult.healthAuthBloc in python will fail. Here's the Pyobjus dump from the last attempt.

[DEBUG] --------------------------------------------------------------------------------
[DEBUG] __call__() configureBlock 0x101a2190 0x7c248870  
[DEBUG] --> want to call configureBlock ()  
[DEBUG] --> return def is ('v', '8', None)  
[DEBUG] --> args def is [('@', '0', None), (':', '4', None)]  
[DEBUG]  - [0] class instance 0x7c248870  
[DEBUG]  - selector is 0x101a1d26  
[DEBUG] --------------------------------------------------------------------------------  
[DEBUG] signature ensure_method --> configureBlock ('v', '8', None)  
[DEBUG] pre-zip signature: [('@', '0', None), (':', '4', None)] 
[DEBUG] array signature zip: [('@', '0', None), (':', '4', None)]  
[DEBUG] input for type_encoding_to_ffitype(type_encoding=v, str_in_union=False)  
[DEBUG] argument ==> ('@', '0', None) 2  
[DEBUG] input for type_encoding_to_ffitype(type_encoding=@, str_in_union=False)  
[DEBUG] argument ==> (':', '4', None) 2  
[DEBUG] input for type_encoding_to_ffitype(type_encoding=:, str_in_union=False)  
[DEBUG] --- really call configureBlock with args () (signature is [('@', '0', None), (':', '4', None)])  
[DEBUG]    > 0: 2081754344  
[DEBUG]    > 1: 2081754348  
[INFO] return signature v  
Request Auth
[DEBUG] --------------------------------------------------------------------------------  
[DEBUG] __call__() healthAuthBlock 0x101a2190 0x7c248870  
[DEBUG] --> want to call healthAuthBlock ()  
[DEBUG] --> return def is ('@?', '8', None)  
[DEBUG] --> args def is [('@', '0', None), (':', '4', None)]  
[DEBUG]  - [0] class instance 0x7c248870  
[DEBUG]  - selector is 0x101a1d46  
[DEBUG] --------------------------------------------------------------------------------  
[DEBUG] signature ensure_method --> healthAuthBlock ('@?', '8', None)  
[DEBUG] pre-zip signature: [('@', '0', None), (':', '4', None)]  
[DEBUG] array signature zip: [('@', '0', None), (':', '4', None)]  
[DEBUG] input for type_encoding_to_ffitype(type_encoding=@?, str_in_union=False)  
 
Exception Exception: Exception("Missing encoding for '@?'",) in 'pyobjus.pyobjus.type_encoding_to_ffitype' ignored
[DEBUG] argument ==> ('@', '0', None) 2  
[DEBUG] input for type_encoding_to_ffitype(type_encoding=@, str_in_union=False)  
[DEBUG] argument ==> (':', '4', None) 2  
[DEBUG] input for type_encoding_to_ffitype(type_encoding=:, str_in_union=False)


What's going on here? It looks like the type encoding isn't set right??? Does that mean that pyobjus needs to have some type of block / namespace encoding?


Has anyone solve this yet?

Michael

unread,
Aug 1, 2020, 9:34:33 AM8/1/20
to Kivy users support
Were you able to make any progress on this? I am interested in making a Healthkit Kivy application, but I am running into a multitude of problems.

Kevin Russell

unread,
Aug 1, 2020, 10:28:28 AM8/1/20
to Kivy users support
Yes I got this to work but basically you have to make a objc dylib to run the code and then call it through pyobjus. Major pain in the butt but it’s easier than making several different apps in different languages I guess.

Here’s my implementation
https://www.dropbox.com/sh/cxp3dppqs936aqu/AADzbGZ65I0bCGRBBHIG0eWha?dl=0

Michael

unread,
Aug 1, 2020, 11:02:24 AM8/1/20
to Kivy users support
Thank you so much for the quick response. I am going to try and work with what you gave me to make a healthkit app. If everything comes to fruition ill be sure to cite you in the acknowledgments!

Michael

unread,
Aug 1, 2020, 12:39:41 PM8/1/20
to Kivy users support
For implementation, what was your method for loading the dylib into your app? I am able to run test code on my MacOS interpreter but everything breaks down once I start using buildozer/kivy-ios.
Reply all
Reply to author
Forward
0 new messages