Created
May 20, 2011 01:18
-
-
Save laurie71/982157 to your computer and use it in GitHub Desktop.
test harness for proxying c++ classes in v8/node
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
#include <v8.h> | |
#include <node.h> | |
#include <node_object_wrap.h> | |
#include "Vector.h" | |
using namespace v8; | |
using namespace node; | |
extern "C" { | |
static void init (Handle<Object> target) { | |
Vector::Initialize(target); | |
} | |
NODE_MODULE(test, init); | |
} |
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
#include "Vector.h" | |
Persistent<FunctionTemplate> Vector::ctor; | |
void | |
Vector::Initialize(Handle<Object> target) { | |
HandleScope scope; | |
ctor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New)); | |
ctor->InstanceTemplate()->SetInternalFieldCount(1); | |
ctor->SetClassName(String::NewSymbol("Vector")); | |
// ctor->PrototypeTemplate()->SetAccessor(String::NewSymbol("x"), GetX, SetX); | |
ctor->InstanceTemplate()->SetAccessor(String::NewSymbol("x"), GetX, SetX); | |
target->Set(String::NewSymbol("Vector"), ctor->GetFunction()); | |
} | |
Handle<Value> | |
Vector::New(const Arguments &args) { | |
float x, y, z; | |
HandleScope scope; | |
if (args.Length() == 1 && args[0]->IsArray()) { | |
x = args[0]->ToObject()->Get(0)->NumberValue(); | |
y = args[0]->ToObject()->Get(1)->NumberValue(); | |
z = args[0]->ToObject()->Get(2)->NumberValue(); | |
} else { | |
x = args[0]->IsNumber() ? args[0]->NumberValue() : 0; | |
y = args[1]->IsNumber() ? args[1]->NumberValue() : 0; | |
z = args[2]->IsNumber() ? args[2]->NumberValue() : 0; | |
} | |
Vector* obj = new Vector(x, y, z); | |
obj->Wrap(args.This()); | |
return args.This(); | |
} | |
Vector::Vector(btScalar &x, btScalar &y, btScalar &z) { | |
// m_btVector3 = new btVector3(x, y, z); | |
m_btVector3 = new VectorNative(x, y, z); | |
} | |
Handle<Value> | |
Vector::GetX(Local<String> property, const AccessorInfo& info) { | |
HandleScope scope; | |
// Vector* v = ObjectWrap::Unwrap<Vector>(info.This()); // This vs. Holder? | |
Vector* v = ObjectWrap::Unwrap<Vector>(info.Holder()); // This vs. Holder? | |
Local<Number> result = Number::New(v->m_btVector3->getX()); | |
return scope.Close(result); | |
} | |
void | |
Vector::SetX(Local<String> property, Local<Value> value, const AccessorInfo& info) { | |
Vector* v = ObjectWrap::Unwrap<Vector>(info.Holder()); | |
v->m_btVector3->setX(value->NumberValue()); | |
} |
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
#ifndef __NODE_VECTOR_H__ | |
#define __NODE_VECTOR_H__ | |
#include <node.h> | |
// #include "btBulletDynamicsCommon.h" | |
#include "VectorNative.h" | |
using namespace v8; | |
using namespace node; | |
class Vector: public node::ObjectWrap { | |
public: | |
static Persistent<FunctionTemplate> ctor; | |
static void Initialize(Handle<Object> target); | |
static Handle<Value> GetX(Local<String> property, const AccessorInfo& info); | |
static void SetX(Local<String> property, Local<Value> value, const AccessorInfo& info); | |
protected: | |
static Handle<Value> New(const Arguments &args); | |
Vector(btScalar &x, btScalar &y, btScalar &z); | |
private: | |
// btVector3* m_btVector3; | |
VectorNative* m_btVector3; | |
}; | |
#endif |
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
// Trivial mock of the class being wrapped/proxied | |
#define btScalar float | |
class VectorNative { | |
public: | |
VectorNative(btScalar _x, btScalar _y, btScalar _z) : x(_x), y(_y), z(_z) {} | |
btScalar getX() { return x; } | |
btScalar getY() { return y; } | |
btScalar getZ() { return z; } | |
btScalar setX(btScalar v) { x = v; } | |
btScalar setY(btScalar v) { y = v; } | |
btScalar setZ(btScalar v) { z = v; } | |
private: | |
btScalar x, y, z; | |
}; |
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 Vector = require('./build/default/test.node').Vector; | |
console.log('Vector is '+Vector); | |
console.log('Vector.proto is '+Vector.prototype); | |
var v = new Vector(1,2,3); | |
console.log('v is',v); | |
console.log('v.x is ',v.x); | |
v.x = 9; | |
console.log('v is',v); | |
console.log('v.x is ',v.x); | |
// create sub-type | |
function f() {}; f.prototype = Vector.prototype; | |
function g() { Vector.apply(this, arguments) }; | |
g.prototype = new f(); | |
v = new g(1,2,3); | |
console.log('v is',v); | |
console.log('v.x is ',v.x); |
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
srcdir = '.' | |
blddir = 'build' | |
VERSION = '0.0.1' | |
def set_options(opt): | |
opt.tool_options('compiler_cxx') | |
def configure(conf): | |
conf.check_tool('compiler_cxx') | |
conf.check_tool('node_addon') | |
def build(bld): | |
obj = bld.new_task_gen('cxx', 'shlib', 'node_addon') | |
obj.source = bld.glob('*.cc') | |
obj.target = 'test' |
UPDATE: this looked promising but doesn't fix anything really; it gets rid of one assertion crash, but has no useful effect...
A possible work-around for fixing inheritance: essentially, a c++ emulation of this pattern:
function f(args...) { if (! (this instanceof f)) return new f(args...) }
I suspect there must be a better way though... here's the code (insert at beginning of Vector::New):
if (! args.IsConstructCall()) {
const int argc = args.Length();
Handle<Function> rctor(Function::Cast(*args.Callee()));
// return rctor->NewInstance(argc, args);
std::vector<Handle<Value> > av(static_cast<size_t>(argc), Undefined());
for (int i = 0; i < argc; i++) av[i] = args[i];
return rctor->NewInstance(argc, &av[0]);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code supports questions I'm asking on the Node and v8 mailing lists:
http://groups.google.com/group/nodejs/browse_thread/thread/1af07a2b193fc93
http://groups.google.com/group/v8-users/browse_thread/thread/3d473ed223a4139f
To try it locally (assuming you have Node installed):
$ git clone git://gist.github.com/######.git
$ cd 982157
$ node-waf configure build
$ node VectorTests.js
where ###### is the appropriate gist version (982157 currently).