Where possible types are mapped directly from Python to Objective C
Python type | Objective-C type |
---|---|
int | int/NSNumber (32 bit signed) |
str | NSString (Unicode only) |
None | nil/NSNull in collections |
bool | BOOL/NSNumber |
dict | NSMutableDictionary |
list | NSMutableArray |
Note
The mutable forms of NSDictionary and NSArray (but not NSString) are always created by the MiniPython code. When they come from outside attempts are made to detect that they are the mutable versions before performing mutating operations, but in general that doesn’t work (eg isKindOfClass will return true even when it isn’t). Consequently you will get Objective C level exceptions performing mutating operations on NSDictionary/Array that came from outside of MiniPython.
You can make methods available to the Python by calling MiniPython addModule:named:. Supply a delegate instance and what its name inside MiniPython should be.
Only a first method name part should be present, with the number of colons matching the number of parameters. For example ameth:(id)arg1 :(id)arg2 is fine while ameth:(id)arg1 foo:(id)arg2 is not. You can supply methods with the same name but differing numbers of arguments. Only methods directly implemented in the delegate are callable - those in parent classes are not.
@implementation timeinfo
{
// Weak ensures we don't have a reference cycle
MiniPython* __weak mp;
}
// not callable due to multiple name parts
- (void) init:(MiniPython*)mp_ withName:(NSString*)name {
if((self=[super init])) {
// save a copy so we can set errors
mp=mp_;
[mp addModule:mp_ named:name];
}
return self;
}
// using regular types from table above
- (BOOL) isdst { return NO; }
- (int) day_of_week:(int)year :(int)month :(int)day { return 2; }
- (int) sum_all:(NSArray*)items {
// Note: item's type is not guaranteed beyond being an id. You should check.
if(![items isKindOfClass:[NSArray class]]) {
[mp setError:MiniPythonTypeError reason:
[NSString stringWithFormat:@"Expected list not %@", [mp toPyTypeString:items]]
userInfo:nil];
// return value is ignored
return 0;
}
// dummy code
return 17;
}
// You can use other types
- (Widget*) get_widget { return [[Widget alloc] init]; }
- (void) show_widget:(Widget*)w :(BOOL)show {
if(show) [w show]; else [w hide];
}
@end
MiniPython *mp=[[MiniPython alloc] init];
[[timeinfo alloc] init:mp withName:@"example"];
You can then call these from Python.
print example.isdst()
print example.sum_all([1,2,3,4])
w=example.get_widget()
example.show_widget(w, True)
To report an error you need to invoke setError: reason: userInfo: on the MiniPython instance. The code above has an example of issuing a TypeError.
setCode: error: and callObject: args: error: both take an in parameter of NSError**. If an error occurs it will point to an NSError. The domain will have the value as pointed to by MiniPythonErrorDomain and the code will be from the MiniPythonErrorCode enumeration.
A place to handle platform behaviour
- - ( void ) onError:( NSError * )e
Called whenever there is an error.
This provides one spot where you can perform logging and other diagnostics.
- - ( void ) print:( NSString * )s
Called with a complete string from a print call/statement. It will be newline terminated, unless the print statement had a trailing comma.
- - ( void ) setClient:( id < MiniPythonClientDelegate > )client
Delegate to use for platform behaviour.
Param client: Replaces existing client with this one.
- - ( BOOL ) setCode:( NSInputStream * )code error:( NSError * * )error
Loads and executes byte code
Param code: The inputstream must already be opened
- - ( void ) clear
Removes all internal state.
This ensures that garbage collection is easier. You can reuse this instance by calling addModule:named: to reregister modules and setCode:error: to run new code.
- - ( void ) addModule:( NSObject * )module named:( NSString * )name
Makes methods implemented in module available within Python code as module name.
See adding methods for details on which methods are made available.
- - ( NSObject * ) callMethod:( NSString * )name args:( NSArray * )args error:( NSError * * )error
Calls a method in Python and returns the result
Param name: Global method name Param args: list of arguments that it takes If an error occurs then nil will be returned and error (if supplied) will point to the NSError.
- - ( BOOL ) isCallable:( NSObject * )object
Returns YES if the object is a MiniPython object and can be called. This is useful if you need to do type checking.
- - ( NSObject * ) callObject:( NSObject * )object args:( NSArray * )args error:( NSError * * )error
Calls a method in Python and returns the result
Param name: Global method name Param args: list of arguments that it takes If an error occurs then nil will be returned and error (if supplied) will point to the error.
- + ( NSString * ) toPyString:( NSObject * )value
Returns a string representing the object using Python nomenclature where possible
For example nil is returned as None, YES as True etc. Container types like dict/NSDictionary and list/NSArray will include the items.
- + ( NSString * ) toPyTypeString:( NSObject * )value
Returns a string representing the type of the object using Python nomenclature where possible
For example nil is returned as NoneType, YES as bool, NSDictionary as dict etc.
Param value: Object whose type to stringify
- + ( NSString * ) toPyReprString:( NSObject * )value
Same as toPyString except strings are quoted and backslash escaped. If you emit an error message this is preferable as it makes it clear a value is a string.
- - ( void ) setError:( enum MiniPythonErrorCode )code reason:( NSString * )reason userInfo:( NSDictionary * )userinfo
Use this function to indicate an error has occurred, for example in a module method. See also Errors.
- - ( void ) setNSError:( NSError * )error
Similar to setError:readon:userInfo: except supplying a generic NSError.
- - ( NSError * ) getError
Returns the most recent error