-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Adding new extensions
##API
All extensions should extend JPExtension
:
@protocol JPExtensionProtocol <NSObject>
@optional
- (void)main:(JSContext *)context;
- (size_t)sizeOfStructWithTypeEncoding:(NSString *)typeEncoding;
- (NSDictionary *)dictOfStruct:(void *)structData typeEncoding:(NSString *)typeEncoding;
- (void)structData:(void *)structData ofDict:(NSDictionary *)dict typeEncoding:(NSString *)typeEncoding;
@end
@interface JPExtension : NSObject <JPExtensionProtocol>
+ (instancetype)instance;
- (void *)formatPointerJSToOC:(JSValue *)val;
- (id)formatPointerOCToJS:(void *)pointer;
- (id)formatJSToOC:(JSValue *)val;
- (id)formatOCToJS:(id)obj;
@end
##Add support for struct
Struct is represented as hash object in JS, which is NSDictionary
in OC. So we should convert struct
to NSDictionary
when passing from OC to JS, and covert NSDictionary
to struct
when passing from JS to OC.
Implement the 3 methods related with struct in JPExtensionProtocol
to add support for the custom struct type, for example:
@interface JPCGTransform : JPExtension
@end
@implementation JPCGTransform
- (size_t)sizeOfStructWithTypeEncoding:(NSString *)typeEncoding
{
if ([typeEncoding rangeOfString:@"CGAffineTransform"].location == 1) {
return sizeof(CGAffineTransform);
}
return 0;
}
- (NSDictionary *)dictOfStruct:(void *)structData typeEncoding:(NSString *)typeEncoding
{
if ([typeEncoding rangeOfString:@"CGAffineTransform"].location == 1) {
CGAffineTransform *trans = (CGAffineTransform *)structData;
return @{@"tx": @(trans->tx), @"ty": @(trans->ty), @"a": @(trans->a), @"b": @(trans->b), @"c": @(trans->c), @"d": @(trans->d)};
}
return nil;
}
- (void)structData:(void *)structData ofDict:(NSDictionary *)dict typeEncoding:(NSString *)typeEncoding
{
if ([typeEncoding rangeOfString:@"CGAffineTransform"].location == 1) {
trans->tx = [dict[@"tx"] floatValue];
trans->ty = [dict[@"ty"] floatValue];
trans->a = [dict[@"a"] floatValue];
trans->b = [dict[@"b"] floatValue];
trans->c = [dict[@"c"] floatValue];
trans->d = [dict[@"d"] floatValue];
}
}
@end
Struct type CGAffineTransform
is avaliable in JS now:
require('JPEngine').addExtensions([require('JPCGTransform').instance()])
var view = require('UIView').alloc().init()
view.setTransform({a:1, b:0, c:0, d:1, tx:0, ty:100})
The param typeEncoding
is value of @encode(structType)
:
typedef struct CustomStruct {
int num;
char *name;
} CustomStruct;
NSLog(@"%s", @encode(CGRect)) //{CGRect={CGPoint=dd}{CGSize=dd}}
NSLog(@"%s", @encode(CGAffineTransform)) //{CGAffineTransform=dddddd}
NSLog(@"%s", @encode(CustomStruct)); //{CustomStruct=i*}
##Add JS methods
The -main:
method in JPExtension
will be executed when the extension added to JPEngine
, so we can add JS methods in -main:
.
The 4 formatXXX
methods are used for tranlate types through OC and JS, use -formatPointerJSToOC:
/ -formatJSToOC:
to convert params from JS to OC, use -formatPointerOCToJS:
/ -formatOCToJS:
to convert return value from OC to JS. Example:
@interface JPMemory : JPExtension
@end
@implementation JPMemory
- (void)main:(JSContext *)context
{
context[@"malloc"] = ^id(size_t size) {
void *m = malloc(size);
return [self formatPointerOCToJS:m];
};
context[@"free"] = ^id(JSValue *jsVal) {
void *m = [self formatPointerJSToOC:jsVal];
free(m)
};
}
@end
Now we can use malloc()
and free()
in JS:
require('JPEngine').addExtensions([require('JPMemory').instance()])
var m = malloc(1024)
free(m)