Created
August 18, 2011 15:00
-
-
Save TooTallNate/1154236 to your computer and use it in GitHub Desktop.
An example of adding Objective-C style @try/@catch support to node-ffi. Forkworthy?
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
diff --git a/src/ffi.h b/src/ffi.h | |
index fe29e71..770bc73 100644 | |
--- a/src/ffi.h | |
+++ b/src/ffi.h | |
@@ -40,49 +40,49 @@ class Pointer : public ObjectWrap { | |
Pointer(unsigned char *ptr); | |
~Pointer(); | |
- static void Initialize(Handle<Object> Target); | |
- static Handle<Object> WrapInstance(Pointer *inst); | |
- static Handle<Object> WrapPointer(unsigned char *ptr); | |
+ static void Initialize(v8::Handle<Object> Target); | |
+ static v8::Handle<Object> WrapInstance(Pointer *inst); | |
+ static v8::Handle<Object> WrapPointer(unsigned char *ptr); | |
unsigned char *GetPointer(); | |
void MovePointer(int bytes); | |
void Alloc(size_t bytes); | |
void Free(); | |
protected: | |
- static Handle<Value> New(const Arguments& args); | |
- static Handle<Value> Seek(const Arguments& args); | |
- static Handle<Value> PutInt8(const Arguments& args); | |
- static Handle<Value> GetInt8(const Arguments& args); | |
- static Handle<Value> PutUInt8(const Arguments& args); | |
- static Handle<Value> GetUInt8(const Arguments& args); | |
- static Handle<Value> PutInt16(const Arguments& args); | |
- static Handle<Value> GetInt16(const Arguments& args); | |
- static Handle<Value> PutUInt16(const Arguments& args); | |
- static Handle<Value> GetUInt16(const Arguments& args); | |
- static Handle<Value> PutInt32(const Arguments& args); | |
- static Handle<Value> GetInt32(const Arguments& args); | |
- static Handle<Value> PutUInt32(const Arguments& args); | |
- static Handle<Value> GetUInt32(const Arguments& args); | |
- static Handle<Value> PutInt64(const Arguments& args); | |
- static Handle<Value> GetInt64(const Arguments& args); | |
- static Handle<Value> PutUInt64(const Arguments& args); | |
- static Handle<Value> GetUInt64(const Arguments& args); | |
- static Handle<Value> PutFloat(const Arguments& args); | |
- static Handle<Value> GetFloat(const Arguments& args); | |
- static Handle<Value> PutDouble(const Arguments& args); | |
- static Handle<Value> GetDouble(const Arguments& args); | |
- static Handle<Value> PutPointerMethod(const Arguments& args); | |
- static Handle<Value> GetPointerMethod(const Arguments& args); | |
- static Handle<Value> PutCString(const Arguments& args); | |
- static Handle<Value> GetCString(const Arguments& args); | |
- static Handle<Value> IsNull(const Arguments& args); | |
+ static v8::Handle<v8::Value> New(const Arguments& args); | |
+ static v8::Handle<v8::Value> Seek(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutInt8(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetInt8(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutUInt8(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetUInt8(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutInt16(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetInt16(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutUInt16(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetUInt16(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutInt32(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetInt32(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutUInt32(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetUInt32(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutInt64(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetInt64(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutUInt64(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetUInt64(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutFloat(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetFloat(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutDouble(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetDouble(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutPointerMethod(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetPointerMethod(const Arguments& args); | |
+ static v8::Handle<v8::Value> PutCString(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetCString(const Arguments& args); | |
+ static v8::Handle<v8::Value> IsNull(const Arguments& args); | |
- static Handle<Value> GetAddress(Local<String> name, const AccessorInfo& info); | |
- static Handle<Value> GetAllocated(Local<String> name, const AccessorInfo& info); | |
+ static v8::Handle<v8::Value> GetAddress(Local<String> name, const AccessorInfo& info); | |
+ static v8::Handle<v8::Value> GetAllocated(Local<String> name, const AccessorInfo& info); | |
private: | |
static Persistent<FunctionTemplate> pointer_template; | |
- static Handle<FunctionTemplate> MakeTemplate(); | |
+ static v8::Handle<FunctionTemplate> MakeTemplate(); | |
unsigned char *m_ptr; | |
unsigned int m_allocated; | |
}; | |
@@ -98,23 +98,23 @@ public: | |
class FFI : public ObjectWrap { | |
public: | |
- static void InitializeStaticFunctions(Handle<Object> Target); | |
- static void InitializeBindings(Handle<Object> Target); | |
+ static void InitializeStaticFunctions(v8::Handle<Object> Target); | |
+ static void InitializeBindings(v8::Handle<Object> Target); | |
protected: | |
- static Handle<Value> FFIPrepCif(const Arguments& args); | |
- static Handle<Value> Strtoul(const Arguments& args); | |
+ static v8::Handle<v8::Value> FFIPrepCif(const Arguments& args); | |
+ static v8::Handle<v8::Value> Strtoul(const Arguments& args); | |
}; | |
class ForeignCaller : public ObjectWrap { | |
public: | |
ForeignCaller(); | |
~ForeignCaller(); | |
- static void Initialize(Handle<Object> Target); | |
+ static void Initialize(v8::Handle<Object> Target); | |
protected: | |
- static Handle<Value> New(const Arguments& args); | |
- static Handle<Value> Exec(const Arguments& args); | |
+ static v8::Handle<v8::Value> New(const Arguments& args); | |
+ static v8::Handle<v8::Value> Exec(const Arguments& args); | |
static int AsyncFFICall(eio_req *req); | |
static int FinishAsyncFFICall(eio_req *req); | |
@@ -127,28 +127,28 @@ class ForeignCaller : public ObjectWrap { | |
private: | |
static Persistent<FunctionTemplate> foreign_caller_template; | |
- static Handle<FunctionTemplate> MakeTemplate(); | |
+ static v8::Handle<FunctionTemplate> MakeTemplate(); | |
}; | |
class ThreadedCallbackInvokation; | |
class CallbackInfo : public ObjectWrap { | |
public: | |
- CallbackInfo(Handle<Function> func, void *closure); | |
+ CallbackInfo(v8::Handle<Function> func, void *closure); | |
~CallbackInfo(); | |
- static void Initialize(Handle<Object> Target); | |
- Handle<Value> GetPointerObject(); | |
+ static void Initialize(v8::Handle<Object> Target); | |
+ v8::Handle<v8::Value> GetPointerObject(); | |
static void WatcherCallback(EV_P_ ev_async *w, int revents); | |
protected: | |
static void DispatchToV8(CallbackInfo *self, void *retval, void **parameters); | |
- static Handle<Value> New(const Arguments& args); | |
- static Handle<Value> GetPointer(Local<String> name, const AccessorInfo& info); | |
+ static v8::Handle<v8::Value> New(const Arguments& args); | |
+ static v8::Handle<v8::Value> GetPointer(Local<String> name, const AccessorInfo& info); | |
static void Invoke(ffi_cif *cif, void *retval, void **parameters, void *user_data); | |
private: | |
static Persistent<FunctionTemplate> callback_template; | |
- static Handle<FunctionTemplate> MakeTemplate(); | |
+ static v8::Handle<FunctionTemplate> MakeTemplate(); | |
static pthread_t g_mainthread; | |
static pthread_mutex_t g_queue_mutex; | |
@@ -157,7 +157,7 @@ class CallbackInfo : public ObjectWrap { | |
void *m_closure; | |
Persistent<Function> m_function; | |
- Handle<Object> m_this; | |
+ v8::Handle<Object> m_this; | |
}; | |
class ThreadedCallbackInvokation { | |
diff --git a/src/foreign_caller.cc b/src/foreign_caller.cc | |
index d54fd57..1c41116 100644 | |
--- a/src/foreign_caller.cc | |
+++ b/src/foreign_caller.cc | |
@@ -1,3 +1,4 @@ | |
+#import <Foundation/Foundation.h> | |
#include "ffi.h" | |
ForeignCaller::ForeignCaller() { | |
@@ -8,10 +9,10 @@ ForeignCaller::~ForeignCaller() { | |
Persistent<FunctionTemplate> ForeignCaller::foreign_caller_template; | |
-Handle<FunctionTemplate> ForeignCaller::MakeTemplate() | |
+v8::Handle<FunctionTemplate> ForeignCaller::MakeTemplate() | |
{ | |
- HandleScope scope; | |
- Handle<FunctionTemplate> t = FunctionTemplate::New(New); | |
+ v8::HandleScope scope; | |
+ v8::Handle<FunctionTemplate> t = FunctionTemplate::New(New); | |
Local<ObjectTemplate> inst = t->InstanceTemplate(); | |
inst->SetInternalFieldCount(1); | |
@@ -19,24 +20,24 @@ Handle<FunctionTemplate> ForeignCaller::MakeTemplate() | |
return scope.Close(t); | |
} | |
-void ForeignCaller::Initialize(Handle<Object> target) | |
+void ForeignCaller::Initialize(v8::Handle<Object> target) | |
{ | |
- HandleScope scope; | |
+ v8::HandleScope scope; | |
if (foreign_caller_template.IsEmpty()) { | |
foreign_caller_template = Persistent<FunctionTemplate>::New(MakeTemplate()); | |
} | |
- Handle<FunctionTemplate> t = foreign_caller_template; | |
+ v8::Handle<FunctionTemplate> t = foreign_caller_template; | |
NODE_SET_PROTOTYPE_METHOD(t, "exec", Exec); | |
target->Set(String::NewSymbol("ForeignCaller"), t->GetFunction()); | |
} | |
-Handle<Value> ForeignCaller::New(const Arguments& args) | |
+v8::Handle<Value> ForeignCaller::New(const Arguments& args) | |
{ | |
- HandleScope scope; | |
+ v8::HandleScope scope; | |
ForeignCaller *self = new ForeignCaller(); | |
if (args.Length() == 5) { | |
@@ -60,13 +61,13 @@ Handle<Value> ForeignCaller::New(const Arguments& args) | |
return args.This(); | |
} | |
-Handle<Value> ForeignCaller::Exec(const Arguments& args) | |
+v8::Handle<Value> ForeignCaller::Exec(const Arguments& args) | |
{ | |
- HandleScope scope; | |
+ v8::HandleScope scope; | |
ForeignCaller *self = ObjectWrap::Unwrap<ForeignCaller>(args.This()); | |
if (self->m_async) { | |
- HandleScope scope; | |
+ v8::HandleScope scope; | |
AsyncCallParams *p = new AsyncCallParams(); | |
// cuter way of doing this? | |
@@ -84,17 +85,21 @@ Handle<Value> ForeignCaller::Exec(const Arguments& args) | |
p->emitter = Persistent<Object>::New(emitterConstructor->NewInstance()); | |
ev_ref(EV_DEFAULT_UC); | |
- eio_custom(ForeignCaller::AsyncFFICall, EIO_PRI_DEFAULT, ForeignCaller::FinishAsyncFFICall, p); | |
+ //eio_custom(&ForeignCaller::AsyncFFICall, EIO_PRI_DEFAULT, &ForeignCaller::FinishAsyncFFICall, p); | |
return scope.Close(p->emitter); | |
} | |
else { | |
+@try { | |
ffi_call( | |
self->m_cif, | |
self->m_fn, | |
self->m_res, | |
self->m_fnargs | |
); | |
+} @catch (NSException *ex) { | |
+return v8::ThrowException(Pointer::WrapPointer((unsigned char *)ex)); | |
+} | |
} | |
return Undefined(); | |
@@ -128,4 +133,4 @@ int ForeignCaller::FinishAsyncFFICall(eio_req *req) | |
delete p; | |
return 0; | |
-} | |
\ No newline at end of file | |
+} | |
diff --git a/wscript b/wscript | |
index 2072c58..0804974 100644 | |
--- a/wscript | |
+++ b/wscript | |
@@ -28,6 +28,10 @@ def configure(conf): | |
# the off_t size difference between the way node is compiled | |
# and this will cause the eio_req to be different and crash | |
# the node-ffi stuff | |
+ conf.env.append_value('CCFLAGS', '-ObjC++') | |
+ conf.env.append_value('CXXFLAGS', '-ObjC++') | |
+ conf.env.append_value('CCFLAGS', '-lobjc') | |
+ conf.env.append_value('CXXFLAGS', '-lobjc') | |
conf.env.append_value('CCFLAGS', '-D_LARGEFILE_SOURCE') | |
conf.env.append_value('CXXFLAGS', '-D_LARGEFILE_SOURCE') | |
conf.env.append_value('CCFLAGS', '-D_FILE_OFFSET_BITS=64') | |
@@ -40,6 +44,7 @@ def configure(conf): | |
def build(bld): | |
obj = bld.new_task_gen('cxx', 'shlib', 'node_addon') | |
obj.target = 'ffi_bindings' | |
+ obj.frameworks = [ 'Foundation' ] | |
obj.source = './src/ffi.cc ./src/callback_info.cc ./src/pointer.cc ./src/threaded_callback_invokation.cc ./src/foreign_caller.cc' | |
obj.uselib = 'FFI DL' | |
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('./') | |
, objc = new ffi.Library('libobjc', { | |
objc_msgSend: [ 'pointer', [ 'pointer', 'pointer', ] ] | |
, objc_getClass: [ 'pointer', [ 'string' ] ] | |
, sel_registerName: [ 'pointer', [ 'string' ] ] | |
// try/catch | |
, objc_begin_catch: [ 'pointer', [ 'pointer' ] ] | |
, objc_end_catch: [ 'void', [] ] | |
}) | |
, NSObject = objc.objc_getClass('NSObject') | |
, badSelector = objc.sel_registerName('nonexistantMethod') | |
// Invoke an exception | |
try { | |
objc.objc_msgSend(NSObject, badSelector) | |
} catch (ptr) { | |
console.error("Caught an Objective-C Exception!!!") | |
console.error(ptr) | |
console.trace() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment