RE: Re: Netscape 'Spidermonkey' JavaScript bi ndings
Warrick Buchanan <[email protected]>
| Newsgroups | gmane.comp.lib.boost.langbinding |
|---|---|
| Message-ID | <415C917D807AD411B72C00805FF7330B094C0025@MAILSRV> |
Hi,
The method I've been investigating currently for binding was to generate a
unique jsNative wrapper function that is made unique by the template
parameters of the class type and function signature combined with a unique
id (The <0> etc in my previous examples). So for a function that takes one
argument and returns something it's like (from memory as my code is at home
at the moment):
template<class Class>
struct Declare
{
static std::vector<JSFuncSpec> functionSpecs;
template<int id, class ReturnType, class Arg0Type>
struct BindFunction
{
typedef ReturnType (Class::*Prototype)(Arg0Type);
static Prototype function;
template<int id, class ReturnType, class Arg0Type>
static JSBool Call(JSContext* context, JSObject*
obj, uintN argc, jsval* argv, jsval* rval)
{
Class* instance =
reinterpret_cast<Class*>(JS_GetPrivate(context, obj));
if(instance)
{
*rval = ToJSVal<ReturnType>(context,
function(FromJSVal<Arg0Type>(context, argv[0])));
return JS_TRUE;
}
return JS_FALSE;
}
};
template<int id, class MaybeBaseClass, class ReturnType, class
Arg0Type>
static void Function(const char* const name, ReturnType
(MaybeBaseClass::* function)(Arg0Type))
{
JSFuncSpec funcSpec;
BindFunction<id, ReturnType, Arg0Type>::function =
static_cast<ReturnType (Class::*)(Arg0Type)>(function);
funcSpec.name = name;
funcSpec.call = BindFunction<id, ReturnType,
Arg0Type>::Call;
...
functionSpecs.push_back(funcSpec);
}
};
Does this have less indirection and runtime overhead then your proposed
method? (I'm still mulling over this). Having to use a unique integer ID
for each function and property is bareable but it would be nice if it could
be rigged so the actual pointer to the function or data member could be used
as the template parameter so you could just do:
Declare<Vector3>::Property<&Vector3::z>("z");
Declare<Vector3>::Function<&Vector3::LengthSquared>("lengthSquared");
But alas thus far the closest I've got is something simple like:
template<class Class>
struct Declare
{
template<class Type, Type Class::* member>
static void Property()
{
}
};
...that lets you do:
Declare<Vector3>::Property<float, &Vector3::x>();
Which gets rid of the unique ID business but then you have to specify the
member types directly in the template argument list which is annoying
especially for functions (you have to specify each argument type etc
manually which would be a bore). I can see no way around this at the moment
to make it automatically deduce these?
>Would you be interested in combining efforts on this problem?
Absolutely.
Warrick.
-----Original Message-----
From: Peder Holt [mailto:[email protected]]
Sent: 29 March 2004 19:00
To: [email protected]
Subject: [Boost-langbinding] Re: Netscape 'Spidermonkey' JavaScript
bindings
Warrick Buchanan <warrick <at> argonaut.com> writes:
>
> [Posted through web interface as posting to mailing list doesn't seem to
work?
]
>
> Hi there,
>
> First off thanks to David for letting me know about the existance of this
> list. I currently have the beginnings (compiling with MSVC++ 7.1) of
bindings
> for Netscape's 'Spidermonkey' JavaScript Engine (1.5 RC6) with which I can
do
> stuff like the following:
>
> ...
>
> struct Vector3
> {
> float x, y, z;
>
> float LengthSquared()
> {
> return x*x + y*y + z*z;
> }
> };
>
> Declare<Vector3>::Property<0>("x", &Vector3::x);
> Declare<Vector3>::Property<1>("y", &Vector3::y);
> Declare<Vector3>::Property<2>("z", &Vector3::z);
> Declare<Vector3>::Function<0>("lengthSquared", &Vector3::LengthSquared);
> Declare<Vector3>::Definition("Vector3", jsContext, jsObject, jsPrototype);
>
> ...
>
> Then in JavaScript land I can do:
>
> ...
>
> var v = new Vector3();
>
> v.x = 3.0;
> v.y = 4.0;
> v.z = 5.0;
>
> var l = v.lengthSquared();
>
> ...
>
Hi.
I have started to look into a binder for Netscape's Spidermonkey myself,
building on my experience from the clipp project.
I encountered the problem of uniquely mapping a jsNative function to a c++
function compile time.
I had to adapt to the syntax of boost.python:
class_<T>(...)
.function("f1",f1)
.function("f2",f2);
and for global functions:
module<T>(...)
.function("f1",f1)
.function("f2",f2);
where T is some arbitrary unique type.
The trick here is to let "function" return a specialized indexing class that
points to the next free function pointer for the type T.
template<typename T,unsigned IndexI>
struct callback_function {
JSBool callback(...); //map using typeid(T) or JSObject* and IndexI
};
template<typename DerivedT,unsigned IndexI>
struct indexed_define {
indexed_define(DerivedT*)
template<typename Fn>
indexed_define<DerivedT,IndexI+1> function(const char* name,Fn fn) {
jsNative callback
= callback_function<DerivedT::value_type,IndexI>::callback;
}
};
template<typename T>
struct module : public indexed_define<module,0>
{
typedef T value_type;
};
My knowledge of SpiderMonkey is rudimentary at best, and there might be some
other smart way of avoiding the above problem.
Would you be interested in combining efforts on this problem?
Peder Holt
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
Boost-langbinding mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-langbinding
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click