Embedding SpiderMonkey for scripting custom objects

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Embedding SpiderMonkey for scripting custom objects

Mihai Dobrescu
Hello,

I am a totally newbie to SpiderMonkey embedding.
Basically, I want to embed it in Adobe Illustrator in order to support scripting it and their API is in C++ for C...

I get references to their objects, I need converting etc., but I would like to expose their types to SpiderMonkey.

My first question is how to define the objects in order to operate with them in javascript?

I see a lot of documentation, but not complete examples.

For instance, how would I import enums like below one (from C/C++)?

enum MyEnum {
    One = 0,
    Two,
    Three
};

They have a lot of structs too, I assume these could be objects defined as classes:

typedef struct {
...
    AIReal width, height; // typedef double AIReal, *AIRealPtr;
...
} AIDocumentSetup;

or

struct AIDocumentSuite {
...
AIAPI AIErr (*GetDocumentFileSpecification) ( ai::FilePath &file );
...
};

Here, it is not clear to me how could I define in SpiderMonkey an object called "AIDocumentSuite" having a method "GetDocumentFileSpecification" with a parameter of type "ai_FilePath", for instance.

Also, setters and getters how could they be declared and defined?

Is somebody that kind to point me to a working example?

Thank you.



_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Mihai Dobrescu
Additionally, if I need to ... register, for the future client javascript, a type defined in C as #typedef double AIReal, to work with AIReal instead of double, what should I do?

_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Wes Garland
You're not going to be adding new types to Javascript.  What you should be
doing is translating whatever Adobe gives you to either numbers, strings,
booleans, or objects.  And back. You need to do this conversion at the API
boundary between the two languages.  You will notice that, in JSAPI,
numbers back be backed by either doubles or integers. Do not concern
yourself with this, it is an implementation detail and not part of the JS
language.  You need to think about reflecting your API in terms numbers,
strings, booleans, or objects. And I guess the special values null,
undefined, and functions.

Similarly, there are no enums in Javascript.   One solution I have used for
this in the past is simply to make an object whose properties have  the
correct names and values.  Make the properties immutable and they will
basically work like consts.  This works okay with bitwise math and so on,
but if you need to cast a number back to an enum in JS-land, you'll need to
add a method to the object to accomplish this.

For example, one of my embedding environments has an object named ffi.gpsee
which has POSIX values in it that came from #define... this is similar to
an enum in your case. It lets me write JS code like this:

openlog(currentIdent, ffi.gpsee.LOG_PID,  ffi.gpsee.LOG_LOCAL7 |
ffi.gpsee.LOG_NDELAY);

Wes

On 18 December 2015 at 10:28, <[hidden email]> wrote:

> Additionally, if I need to ... register, for the future client javascript,
> a type defined in C as #typedef double AIReal, to work with AIReal instead
> of double, what should I do?
>
> _______________________________________________
> dev-tech-js-engine mailing list
> [hidden email]
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>



--
Wesley W. Garland
Director, Product Development
PageMail, Inc.
+1 613 542 2787 x 102
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Mihai Dobrescu
In reply to this post by Mihai Dobrescu
Thank you, I understand your point.
Still, assuming I need to pass some object with data as argument, how should this be done?

I see two ways:
1. Define wrappers to pass each data member as basic types (probably not always possible) and to convert them all the time back and forth.
2. Define new object types with data members. Here, I need a full example on how to manage this.

What means to define (for the example sake, I will work with much complex objects) a javascript class for a c++ type like this:

struct Point {
   int x, y;
};

to be used in javascript as "var p = new Point(10, 10); SetPoint(p);",  passed to a method written in C/C++ like:

struct PointOps {
    int (*SetPoint) (Point &p);
};

My question is related to memory management and garbage collection of SpiderMonkey, as I feel I need to manage the Point object p instance somehow, didn't I? (btw, I am a rusty C/C++ developer, I did not use these since 2005)
In other words, is there more to do than defining the class for SpiderMonkey?
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Wes Garland
Provided you don't hold any references in C-land to memory allocated by the
Point constructor, you don't need to do anything fancy to manage the
memory; just implement a finalizer for Point that also needs how to free
the C (or C++) resources allocated by the constructor.  JSAPI will call
your finalizer automatically sometime after the symbol has stopped being
visible to JS.

On 19 December 2015 at 03:44, <[hidden email]> wrote:

> Thank you, I understand your point.
> Still, assuming I need to pass some object with data as argument, how
> should this be done?
>
> I see two ways:
> 1. Define wrappers to pass each data member as basic types (probably not
> always possible) and to convert them all the time back and forth.
> 2. Define new object types with data members. Here, I need a full example
> on how to manage this.
>
> What means to define (for the example sake, I will work with much complex
> objects) a javascript class for a c++ type like this:
>
> struct Point {
>    int x, y;
> };
>
> to be used in javascript as "var p = new Point(10, 10); SetPoint(p);",
> passed to a method written in C/C++ like:
>
> struct PointOps {
>     int (*SetPoint) (Point &p);
> };
>
> My question is related to memory management and garbage collection of
> SpiderMonkey, as I feel I need to manage the Point object p instance
> somehow, didn't I? (btw, I am a rusty C/C++ developer, I did not use these
> since 2005)
> In other words, is there more to do than defining the class for
> SpiderMonkey?
> _______________________________________________
> dev-tech-js-engine mailing list
> [hidden email]
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>



--
Wesley W. Garland
Director, Product Development
PageMail, Inc.
+1 613 542 2787 x 102
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Mihai Dobrescu
In reply to this post by Mihai Dobrescu
Is there a way to derive from a basic type, like double?

_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Wes Garland
No, not without getting deeeep into engine internals, which you really
really do not want to do.

Sent from my iPad

> On Dec 19, 2015, at 10:05 AM, "[hidden email]" <[hidden email]> wrote:
>
> Is there a way to derive from a basic type, like double?
>
> _______________________________________________
> dev-tech-js-engine mailing list
> [hidden email]
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Mihai Dobrescu
In reply to this post by Mihai Dobrescu
For embedding, how is it better?

1. to initialize the global object and classes definitions on application start, to run from time to time the javascripts, to destroy the context and runtime and shutdown the engine at application end,

or

2. to do all the lifecycle for each javascript?

Is there possible interference between scripts in the first case? Is there a cleanup to be done in order to safely run the javascripts?
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Embedding SpiderMonkey for scripting custom objects

Steve Fink-4
In reply to this post by Mihai Dobrescu
On 12/21/2015 10:55 PM, [hidden email] wrote:
> So, is there a way to achieve my goal this way?
>

Removing those scopes doesn't make sense, since then you'll end up
shutting down the request after you've destroyed the runtime.

But really you want to take the approach you originally spelled out --
create the runtime, context, and global once, init all your classes
once, and then every time you want to run script, wrap it in
JSAutoRequest and JSAutoCompartment.

Do not destroy the runtime or context until the final program shutdown.

In your followup, you mentioned using JSAutoRequest* and
JSAutoCompartment*. Don't do that. You want to stack-allocate those RAII
objects.

AFAICT, you're doing the right steps on shutdown -- JS_DestroyContext,
JS_DestroyRuntime and JS_ShutDown.

Make sure you're linking to a debug build of the mozjs library.
(Optimized is ok, though for development it might be better to turn that
off too.) That'll give you many many useful assertions. It's pretty much
impossible to use the JSAPI correctly without them. (For production,
you'd --disable-debug; the assertions make things much slower.)

I'm actually a little unclear as to what your current problems are. It
seems like you're basically doing things correctly, though your test
program is getting the RAII scoping wrong.

_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine