Exposing classes to javascript

343 views
Skip to first unread message

Jacob

unread,
Sep 13, 2008, 11:26:35 AM9/13/08
to v8-users
I want to expose some classes to javascript so users can create
instances of them. From what I can piece together the code might look
something like so

Handle<FunctionTemplate> myObjectCtorFunction =
FunctionTemplate::New(MyObjectCtorCallback);
Handle<ObjectTemplate> myObjectInstanceTempl = myObjectCtorFunction-
>InstanceTemplate();
// setup properties and internal fields on myObjectInstanceTempl

// make ctor available to js
globals->Set("MyObject", myObjectCtorFunction);


Handle<Value> MyObjectCtorCallback(const Arguments& args)
{
// args.IsConstructCall is true if used as ctor ?
// args.Holder() is the already created instance?

// so something like
if (args.IsConstructCall()) {
// create c++ object
// set internal field of args.Holder() with c++ object
return args.Holder()
}

return Undefined();
}


Is this correct? And what about destruction, how do I make sure I can
destroy my c++ object when the js object is collected?

Jacob Burbach

unread,
Sep 13, 2008, 5:04:58 PM9/13/08
to v8-u...@googlegroups.com
After some more digging I think I've got it. Using Persistent::MakeWeak you
can set a callback for the objects destruction. Everything seems to be
working ok now, so I'll attach my code for future users to find. If you see
anything wrong with it please speak up.

Jake

v8test.cpp

baumgartn...@gmail.com

unread,
Sep 22, 2008, 4:57:35 AM9/22/08
to v8-users
Thank you for the example.
I also use:
........
Persistent<Object> self = Persistent<Object>::New(args.Holder());
self.MakeWeak(0, Point_Destroy);

self->SetInternalField(0, External::New(p));
return self;
}
void Point_Destroy(Persistent<Object> self, void* parameter)
{
Local<External> external = Local<External>::Cast(self-
>GetInternalField(0));
delete static_cast<Point*>(external->Value());
}

but the "Point_Destroy" Function is never called. So when should it be
called in your example?

Thanks
bg

corey

unread,
Sep 22, 2008, 11:43:07 AM9/22/08
to v8-users
Would you mind posting the test.js file that is referenced in the
v8test.cpp file as well?

Thanks,
Corey

Northorn

unread,
Sep 25, 2008, 11:07:15 AM9/25/08
to v8-users
I had to put a:

v8::HandleScope handle_scope;

in this function. If not I would occasionally get an error about not
having a handle scope in this function.

Northorn

unread,
Sep 25, 2008, 11:11:57 AM9/25/08
to v8-users
Also, you can use v8::V8::AdjustAmountOfExternalAllocatedMemory() to
tell the GC how much external memory those handles are referring to.

I'm not sure this actually does anything currently. It seems to GC
more based on the number of handles you've allocated. If you're
allocating very large objects very quickly your app will exhaust its
address space and crash before GC kicks in.

Garry

unread,
Sep 26, 2008, 4:55:47 PM9/26/08
to v8-users
Hey - did you solve this problem? I'm facing the same thing right
now..

I want to make an object that I push into Javascript, then when JS
garbage collects it I get a callback so I can delete the c++ side
pointer. Is this the wrong approach?

garry

On Sep 22, 9:57 am, baumgartner.ger...@gmail.com wrote:
> Thank you for the example.
> I also use:
>            ........
>         Persistent<Object> self = Persistent<Object>::New(args.Holder());
>         self.MakeWeak(0, Point_Destroy);
>
>         self->SetInternalField(0, External::New(p));
>         return self;}
>
> void Point_Destroy(Persistent<Object> self, void* parameter)
> {
>         Local<External> external = Local<External>::Cast(self->GetInternalField(0));
>
>        deletestatic_cast<Point*>(external->Value());

bell

unread,
Sep 27, 2008, 4:59:07 AM9/27/08
to v8-users
In my tests, it works, with the MakeWeak-callback. The callback ist
called the first time, when there are about 400 unused Persistent
Objects allocated

i use following js code to test, where the fuction myobj returns a
Persistent Object

for (var c=0;c<200000;c++) {
var x=myobj()
}

unfortuanatly, when i have allocated and deallocated about 160000
objects, my program crashes. it looks like the GarbageCollector isn't
freeing the Persistent Object after calling theMakeWeak-callback.

in my callback i only delete my c++ object, do i have to do something
with the Persistent<Object> ?


markus
> > bg- Zitierten Text ausblenden -
>
> - Zitierten Text anzeigen -

Garry

unread,
Sep 27, 2008, 8:15:51 AM9/27/08
to v8-users
Hi - I realised that in my code the weak function does get called, but
it isn't kicking in until about 4000 objects are created.

I put a counter in my create/destroy functions, and after 10,000
objects are created and I shut down, 3600 still exist undestroyed.

Is there a certain function I should be calling to tell V8 that I've
finished and it's time to collect all those remaining objects?

At the moment the only `shutdown' I'm doing is context.Dispose(); - is
that all that needs to be done?

As for your question, I did notice that in the Chrome code in their
weak gc function they called object.ClearWeak(); - but that might just
be to remove any hanging pointers.

I'd really love to see an official example of this kind of stuff. All
the examples I have found of weak references are using a global or
member var rather than a new/delete system.

garry


On Sep 27, 9:59 am, bell <markus.b...@gmail.com> wrote:
> In my tests, it works, with the MakeWeak-callback. The callback ist
> called the first time, when there are about 400 unused Persistent
> Objects allocated
>
> i use following js code to test, where the fuction myobj returns a
> Persistent Object
>
> for (var c=0;c<200000;c++) {
>    var x=myobj()
>
> }
>
> unfortuanatly, when i have allocated and deallocated about 160000
> objects, my program crashes. it looks like the GarbageCollector isn't
> freeing the Persistent Object after calling theMakeWeak-callback.
>
> in my callback i only delete my c++ object, do i have to do something
> with the Persistent<Object> ?
>
> markus
>
> On 26 Sep., 22:55, Garry <garrynew...@gmail.com> wrote:
>
> > Hey - did you solve this problem? I'm facing the same thing right
> > now..
>
> > I want to make an object that I push into Javascript, then when JS
> >garbagecollects it I get a callback so I can delete the c++ side

deanm

unread,
Sep 27, 2008, 12:15:08 PM9/27/08
to v8-users
A weak callback is called when an object than has a persistent handle
is found unreferenced during garbage collection. This is similar to
"finalizers" in other languages, for example Ruby. This is why you
don't see the function getting called "right away", it will be called
when there is a GC. If you want to trigger a GC, you could look at
the GC extension. For example, when running with --expose-gc, a gc()
method will be installed on the global object. I believe even this is
not guaranteed to collect your objects, it depends how deep of a
garbage collection is performed, and what space your objects are
living in.

Garry

unread,
Sep 27, 2008, 1:36:34 PM9/27/08
to v8-users
Thanks - but what happens on Exit/Shutdown? Is there a method to tell
v8 (or a v8 context) that we're exiting, so it should release
everything?

Although my weak objects get collected after while in normal usage,
the weak reference callback doesn't get called on the objects that
still exist when exiting.

The only thing I've found is calling Dispose on the (single) context -
and that doesn't seem to do anything.

garry

Simon Ask Ulsnes

unread,
Sep 27, 2008, 1:51:09 PM9/27/08
to v8-u...@googlegroups.com
2008/9/27 Garry <garry...@gmail.com>:

> Thanks - but what happens on Exit/Shutdown? Is there a method to tell
> v8 (or a v8 context) that we're exiting, so it should release
> everything?

Normally there is no reason to do any cleanup on process termination,
since all file handles and network connections etc. are automatically
terminated by the file system. All the resources, including memory, of
a process are forcibly released when a process exits, so it's unlikely
that the GC even runs at that time.

If you need to explicitly release a custom resource, you should look
at defining an atexit callback in C++.

Garry

unread,
Sep 27, 2008, 3:30:14 PM9/27/08
to v8-users
Thanks - for future reference for anyone looking for the same thing..
I ``fixed'' this by exposing v8::internal::Heap::CollectAllGarbage()
by adding it to the v8:V8 interface in api.cc

void V8::CollectAllGarbage()
{
i::Heap::CollectAllGarbage();
}

Calling this at choice places (right before exit, after disposing a
context etc) solves the problem completely for me.

Thanks again,

garry


On Sep 27, 6:51 pm, "Simon Ask Ulsnes" <si...@ulsnes.dk> wrote:
> 2008/9/27 Garry <garrynew...@gmail.com>:

Christian Plesner Hansen

unread,
Sep 28, 2008, 3:22:55 PM9/28/08
to v8-u...@googlegroups.com
The external memory counter is really just a hint to the garbage
collector and we may, and probably will, change the exact way it is
used, but here's how it currently works. Whenever garbage is
collected in new-space some of the objects are promoted to old-space,
which is garbage collected less often. Between collections we keep a
count of how much data has been promoted since the last old-space gc
and this number includes the amount of external memory allocated since
the last gc, as set through AdjustAmountOfExternalAllocatedMemory.
One of the rules that determines whether or not to collect old-space
looks at the amount of data that has been promoted, and when it
reaches a certain limit we do a full garbage collection. So it is
indeed used.

Garbage is only collected when new-space is full, so if you allocate
few but extremely big objects you may run out of memory before
new-space has been filled. That could be the explanation for bad
behavior when really big objects are involved.


-- Christian

Christian Plesner Hansen

unread,
Sep 28, 2008, 3:34:52 PM9/28/08
to v8-u...@googlegroups.com
There is no method to shut down v8. We could add support for shutting
v8 down but it cannot be reliably reinitialized so if you intend to
use it again after shutdown it wouldn't work.

If it is important to clean some or all of your objects up then you
could keep a reference to all the current live objects in your own
code. That way you could dispose of them properly yourself exactly
when you need it. It depends on your application whether that is an
appropriate approach, but that's one way to do it.

Christian Plesner Hansen

unread,
Sep 28, 2008, 3:40:27 PM9/28/08
to v8-u...@googlegroups.com
> unfortuanatly, when i have allocated and deallocated about 160000
> objects, my program crashes. it looks like the GarbageCollector isn't
> freeing the Persistent Object after calling theMakeWeak-callback.
>
> in my callback i only delete my c++ object, do i have to do something
> with the Persistent<Object> ?

Yes. The garbage collector intentionally does not dispose the
persistent handle, you have to do that yourself. It also does not
collect the javascript object, since it is being kept alive by the
handle. The reason for this is that it gives you the option to keep
the object alive after you get the callback, which is necessary under
some circumstances. Only if you dispose the handle, and there are no
more persistent handles to the object, does it actually get collected.

Message has been deleted

Jacob Burbach

unread,
Sep 28, 2008, 10:05:57 PM9/28/08
to v8-u...@googlegroups.com

The Point_Destroy function will be called by the garbage collector when there
are no more references to the object.

Jacob Burbach

unread,
Sep 28, 2008, 10:10:10 PM9/28/08
to v8-u...@googlegroups.com
On Monday 22 September 2008 11:43:07 corey wrote:
> Would you mind posting the test.js file that is referenced in the
> v8test.cpp file as well?
The test.js file just created some Point objects to make sure things were
working ok.

bell

unread,
Sep 29, 2008, 2:21:21 AM9/29/08
to v8-users
can you tell me, how to delete the Persistent-handle? can i do this in
the callback? I tried obj.Dispose() obj.Clear() and obj.ClearWeak(),
but nothing changed the behaviour.


On 28 Sep., 21:40, "Christian Plesner Hansen"

baumgartn...@gmail.com

unread,
Sep 29, 2008, 2:29:47 AM9/29/08
to v8-users
I changed the code to:

........
Persistent<Object> self = Persistent<Object>::New(args.Holder());
self.MakeWeak(p, Point_Destroy);

self->SetInternalField(0, External::New(p));
return self;
}

void Point_Destroy(Persistent<Object> self, void* parameter)
{
delete static_cast<Point*>(parameter);
}

because in the previous version were some problems when I tested it
with the javascript file.

On 29 Sep., 04:05, Jacob Burbach <jmburb...@gmail.com> wrote:

Simon Ask Ulsnes

unread,
Sep 29, 2008, 3:01:07 AM9/29/08
to v8-u...@googlegroups.com
Question of interest: Why use a Persistent handle if it's going to be
deleted at some point other than process termination?

- Simon

2008/9/29 bell <marku...@gmail.com>:

bell

unread,
Oct 4, 2008, 8:09:17 AM10/4/08
to v8-users
I'm creating objects (with c++ objects attached) from within the
javascript. the only way I found to call the destuctor of the c++
object while the javascript ist running ist the makeweak-callback,
whitch can only be attached to a pesistent object.

by the way, the problem with the 160000 objects had nothing to do with
the pesistent objects. my fault was, to create a template for every
new object. now i use a global template and the problem is gone.


On 29 Sep., 09:01, "Simon Ask Ulsnes" <si...@ulsnes.dk> wrote:
> Question of interest: Why use a Persistent handle if it's going to be
> deleted at some point other than process termination?
>
> - Simon
>
> 2008/9/29 bell <markus.b...@gmail.com>:
>
>
>
>
>
> > can you tell me, how to delete the Persistent-handle? can i do this in
> > the callback? I tried obj.Dispose() obj.Clear() and obj.ClearWeak(),
> > but nothing changed the behaviour.
>
> > On 28 Sep., 21:40, "Christian Plesner Hansen"
> > <christian.plesner.han...@gmail.com> wrote:
> >> > unfortuanatly, when i have allocated and deallocated about 160000
> >> > objects, my program crashes. it looks like the GarbageCollector isn't
> >> > freeing the Persistent Object after calling theMakeWeak-callback.
>
> >> > in my callback i only delete my c++ object, do i have to do something
> >> > with the Persistent<Object> ?
>
> >> Yes.  The garbage collector intentionally does not dispose the
> >> persistent handle, you have to do that yourself.  It also does not
> >> collect the javascript object, since it is being kept alive by the
> >> handle.  The reason for this is that it gives you the option to keep
> >> the object alive after you get the callback, which is necessary under
> >> some circumstances.  Only if you dispose the handle, and there are no
> >> more persistent handles to the object, does it actually get collected.- Zitierten Text ausblenden -

Jacob

unread,
Oct 6, 2008, 12:57:03 PM10/6/08
to v8-users
On Sep 29, 2:29 am, baumgartner.ger...@gmail.com wrote:
> I changed the code to:
>
> ........
> Persistent<Object> self = Persistent<Object>::New(args.Holder());
> self.MakeWeak(p, Point_Destroy);
>
> self->SetInternalField(0, External::New(p));
> return self;
>
> }
>
> void Point_Destroy(Persistent<Object> self, void* parameter)
> {
> delete static_cast<Point*>(parameter);
> }
>
> because in the previous version were some problems when I tested it
> with the javascript file.

What problems did you encounter exactly? I plan to update my original
example code to reflect all the information gathered in this
discussion, so people can have a solid example to work from.

Jacob Burbach

unread,
Oct 6, 2008, 7:24:44 PM10/6/08
to v8-u...@googlegroups.com
I've cleaned up and fixed the example a bit, based on what I've learned and
what I've read on the list.

CHANGES:
Call the ClearWeak method of the Persistant object in Point_Destroy. This is
done in the v8 tests, so I'll assume they know what they are doing ;-)

Added a getLength method to Point, to demonstrate how methods can be
added/wrapped

Pass the C++ object as parameter to the MakeWeak method for use in
Point_Destroy, as mentioned in the group, and is also done in the v8 tests..

Delete the C++ object via the parameter to MakeWeak,rather than retrieving
the object from the internal field, as mention in the group, and is also
done in the v8 tests..

Added a global counter thats incremented/decremented when object is
created/destroyed. Will almost certainly show uncollected objects at
exit...

You can find latest here: http://home.cfl.rr.com/filedump/v8test.zip

Ben Nolan

unread,
Oct 6, 2008, 8:35:27 PM10/6/08
to v8-u...@googlegroups.com
Hi Jacob,

Pete Gontier

unread,
Oct 6, 2008, 9:26:36 PM10/6/08
to v8-u...@googlegroups.com
On Oct 6, 2008, at 9:57 AM, Jacob wrote:

What problems did you encounter exactly?

Last night, I was working with weak objects and trying to force their collection at predictable times (for testing) by calling the 'gc' extension. Sometimes my callback would fire and sometimes not. I haven't been able to pin down what makes the difference.


Pete Gontier <http://pete.gontier.org/>

Victor Grishchenko

unread,
Oct 7, 2008, 8:21:30 AM10/7/08
to v8-u...@googlegroups.com
On Oct 6, 2008, at 6:57 PM, Jacob wrote:
What problems did you encounter exactly? I plan to update my original
example code to reflect all the information gathered in this
discussion, so people can have a solid example to work from.

I am wrapping a C++ class into a JavaScript class "Buffer". As far as I may see, I proceed along the lines of process.cc example. I create an object template for "Buffer"

Handle<ObjectTemplate> MakeBufferTemplate () {
HandleScope handle_scope;
Handle<ObjectTemplate> result = ObjectTemplate::New();
result->SetInternalFieldCount(1);
result->Set(String::New("append"), FunctionTemplate::New(BufferAppend));

then I put the template into a global variable evb_templ

void InstallBuffer (Local<ObjectTemplate> global) {
HandleScope scope;
Handle<ObjectTemplate> raw_template = MakeBufferTemplate();
evb_templ = Persistent<ObjectTemplate>::New(raw_template);
Handle<FunctionTemplate> create_templ = FunctionTemplate::New(BufferCreate);
create_templ->SetClassName(String::New("Buffer"));
global->Set(String::New("Buffer"), create_templ );

The BufferCreate functions does

Handle<Object> result = evb_templ->NewInstance();
Handle<External> buf_ptr = External::New(buf);
result->SetInternalField(0, buf_ptr);

Basically, it works. Except, when I try to extend the class in my JavaScript code, it fails:

Buffer.prototype.pollObject = BufferPollBencoded;
var buf = new Buffer();
for (key in buf)
print("def: "+key);

Further, in the output I see e.g.

def: append

... but no "def: pollObject"; later it says that

js/base.js:70: TypeError: Object [object Object] has no method 'pollObject'
var torrent = buf.pollObject(specials);

So, Buffer.prototype does not seem to affect the result of new Buffer(). Where is the mistake?

--

   V

Ben Nolan

unread,
Oct 7, 2008, 4:42:15 PM10/7/08
to v8-u...@googlegroups.com
hi victor, study Jacobs example it works correctly with javascript extensions.

Ben


--
Regards,
Ben Nolan

http://bennolan.com/

skype: bennolan
cell: +64 21 770 662

Victor Grishchenko

unread,
Oct 8, 2008, 4:44:56 AM10/8/08
to v8-u...@googlegroups.com
On Oct 7, 2008, at 10:42 PM, Ben Nolan wrote:
> hi victor, study Jacobs example it works correctly with javascript
> extensions.

Cool. It works. I added an example of object wrapping.

--

V

v8test+wrapping.zip

gritzko

unread,
Oct 8, 2008, 5:27:57 AM10/8/08
to v8-users
At v8test.cpp:59 I have a bug. It does not surface in this sample, but
causes weird behavior in my big program, so:

< pointtemplate = *pointFunctionTemplate;
---
> pointtemplate = Persistent<FunctionTemplate>::New(pointFunctionTemplate);

What is the semantics of Persistent<T>(Handle<S>) and
Persistent<T>(S*) constructors?
The behavior is totally different from Persistent<T>::New(Handle<S>).
I've got into this trap twice.

On Oct 8, 10:44 am, Victor Grishchenko <victor.grishche...@gmail.com>
wrote:

Ben Nolan

unread,
Oct 8, 2008, 5:45:53 AM10/8/08
to v8-u...@googlegroups.com
I've been playing with making something like secondlife, using Ogre
(scenegraph) and v8. Here is one of the ogre classes (the vector3
class) exposed as a javascript object. I believe it'll leak memory a
bit - I plan on fixing with MakeWeak later on.

Might be a nice reference for someone.

Ben

#include <v8.h>
#include <Ogre.h>

#define V8CALLBACK(type, name)\
v8::Handle<v8::Value> type ## _ ## name(const v8::Arguments& args)
#define V8_GETTER(type, property) \
v8::Handle<v8::Value> type ## _get ##
property(v8::Local<v8::String> property, const v8::AccessorInfo& args)
#define V8_SETTER(type, property) \
void type ## _set ## property(v8::Local<v8::String> property,
v8::Local<v8::Value> value, const v8::AccessorInfo& args)
#define V8INTERNAL(type)\
(static_cast<type>(v8::Local<v8::External>::Cast(args.Holder()-
>GetInternalField(0))->Value()))
#define V8ARGUMENT(type, index)\
(static_cast<type>(v8::Local<v8::External>::Cast(args[index]-
>ToObject()->GetInternalField(0))->Value()))
#define V8ARGUMENTTYPE(type, index)\
( \
args[index]->IsObject() \
&& (args[index]->ToObject()->InternalFieldCount()==2) \
&& (*v8::String::Utf8Value(args[index]->ToObject()-
>GetInternalField(1)->ToString())==std::string(type)) \
)

namespace JSVector{

v8::Handle<v8::ObjectTemplate> instance_template;
v8::Handle<v8::FunctionTemplate> function_template;

V8CALLBACK(Vector,getDistance){
if (!V8ARGUMENTTYPE("Vector", 0))
return ThrowException(v8::String::New("Invalid argument"));

return v8::Number::New(V8INTERNAL(Ogre::Vector3*)-
>distance(*V8ARGUMENT(Ogre::Vector3*, 0)));
}

V8CALLBACK(Vector,getLength){
return v8::Number::New(V8INTERNAL(Ogre::Vector3*)->length());
}

V8CALLBACK(Vector,getNormalized){
return JSVector::New(V8INTERNAL(Ogre::Vector3*)->normalisedCopy());
}

V8_GETTER(Vector,x){
return v8::Number::New(V8INTERNAL(Ogre::Vector3*)->x);
}

V8_SETTER(Vector,x){
V8INTERNAL(Ogre::Vector3*)->x = value->NumberValue();
}

V8_GETTER(Vector,y){
return v8::Number::New(V8INTERNAL(Ogre::Vector3*)->y);
}

V8_SETTER(Vector,y){
V8INTERNAL(Ogre::Vector3*)->y = value->NumberValue();
}

V8_GETTER(Vector,z){
return v8::Number::New(V8INTERNAL(Ogre::Vector3*)->z);
}

V8_SETTER(Vector,z){
V8INTERNAL(Ogre::Vector3*)->z = value->NumberValue();
}

/* Sets internal fields with our idiom of storing the class name in
the second field */
void setInternalFields(v8::Persistent<v8::Object> p, Ogre::Vector3
v){
p->SetInternalField(0, v8::External::New(new
Ogre::Vector3(v.ptr())));
p->SetInternalField(1, v8::String::New("Vector"));
}

/* Construct a new vector */
V8CALLBACK(Vector,create){
if (!args.IsConstructCall())
return ThrowException(v8::String::New("Cannot call constructor
as function"));

v8::Persistent<v8::Object> self =
v8::Persistent<v8::Object>::New(args.Holder());
setInternalFields(self, Ogre::Vector3::ZERO);

return self;
}

/* Only called from c++ */
v8::Handle<v8::Value> New(Ogre::Vector3 v){
v8::Persistent<v8::Object> instance =
v8::Persistent<v8::Object>::New(function_template->GetFunction()-
>NewInstance());
setInternalFields(instance, v);
return instance;
}

/* Create the function and instance templates and register the
Vector constructor */

void Initialize(v8::Handle<v8::ObjectTemplate> global){
// Function Template
function_template = v8::FunctionTemplate::New(Vector_create);
function_template->SetClassName(v8::String::New("Vector"));

// Instance template
instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(2);

instance_template->SetAccessor(v8::String::New("x"), Vector_getx,
Vector_setx);
instance_template->SetAccessor(v8::String::New("y"), Vector_gety,
Vector_sety);
instance_template->SetAccessor(v8::String::New("z"), Vector_getz,
Vector_setz);
instance_template->Set("getDistance",
v8::FunctionTemplate::New(Vector_getDistance));
instance_template->Set("getLength",
v8::FunctionTemplate::New(Vector_getLength));
instance_template->Set("getNormalized",
v8::FunctionTemplate::New(Vector_getNormalized));

global->Set(v8::String::New("Vector"), function_template); // add
our Point object
}

}

Morgain...@googlemail.com

unread,
Oct 11, 2008, 1:57:39 AM10/11/08
to v8-users


On Oct 8, 10:45 am, Ben Nolan <bno...@gmail.com> wrote:
> I've been playing with making something like secondlife, using Ogre  
> (scenegraph) and v8.

Very cool, Ben.

If you're active in-world in Second Life as well, then you probably
know me from the AWG and Zero's office hours.

Refactoring the SL client was one of the earliest things I was trying
to encourage, and reorganizing the code into subsystems with APIs
called from a fast scripting language was a key part of the
refactoring process. It sounds like you're doing exactly that,
replacing their bespoke graphics engine with Ogre plus a nice fast
Javascript engine -- excellent! :-)

Are your prim scripts going to be powered by client-side V8 VMs too?
One of the (many) non-scalabilities in Second Life is that prim
scripts run server-side only, so power consumed doesn't scale as the
population grows. Are you intending to distribute some of the server-
side scripting load down to your client V8's too?

Morgaine.

august

unread,
Oct 28, 2008, 6:52:02 PM10/28/08
to v8-users
this code has been really really helpful.

what compiler are you guys using?

I keep getting these errors with g++ version 4.2.4:

v8test.cpp: In function 'v8::Handle<v8::Value> Point_Create(const
v8::Arguments&)':
v8test.cpp:123: error: invalid conversion from 'void (*)
(v8::Persistent<v8::Object>, void*)' to 'void (*)
(v8::Persistent<v8::Value>, void*)'
v8test.cpp:123: error: initializing argument 2 of 'void
v8::Persistent<T>::MakeWeak(void*, void (*)(v8::Persistent<v8::Value>,
void*)) [with T = v8::Object]'
scons: *** [v8test.o] Error 1
scons: building terminated because of errors.

thanks -august.

corey

unread,
Oct 28, 2008, 7:35:33 PM10/28/08
to v8-users
The latest code changes the callback function signature that you pass
to the MakeWeak function.
The function signature should take a Value type instead of an Object
type like this:
void objectDestroy(v8::Persistent<v8::Value> self, void* parameter);

Then when you call:
foo.MakeWeak(0, objectDestroy);

the compiler will see a callback function with the correct sig.

Corey

august

unread,
Oct 31, 2008, 11:04:27 AM10/31/08
to v8-users
ah! thanks. gotit.
Reply all
Reply to author
Forward
0 new messages