Skip to content

Instantly share code, notes, and snippets.

@TooTallNate
Created August 18, 2011 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TooTallNate/1154236 to your computer and use it in GitHub Desktop.
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?
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'
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