Created
July 13, 2011 05:07
-
-
Save TooTallNate/1079750 to your computer and use it in GitHub Desktop.
Experimentations with node-ffi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ffi = require('node-ffi') | |
, objc = new ffi.Library(null, { | |
'objc_getClass': [ 'pointer', [ 'string' ] ] | |
, 'class_getName': [ 'string', [ 'pointer' ] ] | |
, 'sel_registerName': [ 'pointer', [ 'string' ] ] | |
, 'sel_getName': [ 'string', [ 'pointer' ] ] | |
, 'objc_msgSend': [ 'pointer', [ 'pointer', 'pointer' ] ] | |
}) | |
// The problem with libffi and C functions that accepts varargs is that we | |
// have to create new wrappers for each different argument and return value | |
// signature that we encounter | |
, objc1 = new ffi.Library(null, { | |
'objc_msgSend': [ 'pointer', [ 'pointer', 'pointer', 'int32' ] ] | |
}) | |
, objc2 = new ffi.Library(null, { | |
'objc_msgSend': [ 'string', [ 'pointer', 'pointer' ] ] | |
}) | |
, objc3 = new ffi.Library(null, { | |
'objc_msgSend': [ 'pointer', [ 'pointer', 'pointer', 'pointer' ] ] | |
}) | |
, objc4 = new ffi.Library(null, { | |
'objc_msgSend': [ 'pointer', [ 'pointer', 'pointer', 'string' ] ] | |
}) | |
, getClass = objc.objc_getClass | |
// dlopen equivalent | |
new ffi.DynamicLibrary('/System/Library/Frameworks/Foundation.framework/Foundation'); | |
new ffi.DynamicLibrary('/System/Library/Frameworks/ScriptingBridge.framework/ScriptingBridge'); | |
function $C (v) { | |
return getClass(v); | |
} | |
function $R (v) { | |
return objc.sel_registerName(v); | |
} | |
function $D (v) { | |
return objc2.objc_msgSend(objc.objc_msgSend(v, description), objc.sel_registerName('UTF8String')); | |
} | |
var NSAP = $C('NSAutoreleasePool') | |
, alloc = $R('alloc') | |
, init = $R('init') | |
, pool = objc.objc_msgSend(objc.objc_msgSend(NSAP, alloc), init); | |
var NSArray = $C('NSMutableArray'); | |
console.log(NSArray.address); | |
console.log(objc.class_getName(NSArray)); | |
var NSString = $C('NSString') | |
, stringWithUTF8String = $R('stringWithUTF8String:') | |
, str = objc4.objc_msgSend(NSString, stringWithUTF8String, 'Hello Objective-C!') | |
, description = $R('description') | |
console.log($D(str)); | |
var initWithCapacity = $R('initWithCapacity:') | |
, addObject = $R('addObject:') | |
console.log(objc.sel_getName(alloc)); | |
var array = objc.objc_msgSend(NSArray, alloc); | |
array = objc1.objc_msgSend(array, init, 10); | |
objc3.objc_msgSend(array, addObject, NSArray); | |
objc3.objc_msgSend(array, addObject, str); | |
console.log($D(array)); | |
// Normally this wouldn't work properly. However we have dynamically loaded the | |
// ScriptingBridge framework binary file above so this will work properly. | |
var SBApplication = objc.objc_getClass('SBApplication'); | |
console.log(SBApplication.address); | |
console.log(objc.class_getName(SBApplication)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ffi = require('node-ffi') | |
, stdio = new ffi.Library(null, { | |
'printf': [ 'int32', [ 'string', 'string' ]] | |
}) | |
stdio.printf('hello %s\n', 'world'); | |
// hello world |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ffi = require('node-ffi') | |
, time = new ffi.Library(null, { | |
'time': [ 'int32', [ 'pointer' ] ] | |
}) | |
, NULL = new ffi.Pointer(0) | |
// Passing JS null converts to C NULL | |
console.log(time.time(null)); | |
// new ffi.Pointer(0) creates a NULL pointer | |
console.log(time.time(NULL)); | |
var time_t = new ffi.Pointer(4); | |
console.log(time.time(time_t)); | |
console.log(time_t.getInt32()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment