Http://www.ibm.com/developerworks/cn/linux/l-cn-spidermonkey/index.html

Source: Internet
Author: User
Tags access properties define function
ArticleDirectory
    • Exploration of the C-language-based JavaScript Engine
Exploration of the C-language-based JavaScript Engine

Use spidermonkey to script your application

Qiu Juntao, software engineer, yundian Tongfang R & D center

Qiu Juntao graduated from Kunming University of Science and Technology in computer science and technology. He is interested in mechanical control, electronics, artificial intelligence, functional programming, and other fields, familiar with the underlying computer science. C, Java, Python, JavaScript, and other languages are preferred. He is now at the cloud power Tongfang R & D center.

Introduction:The javascript language is dynamic, supports functional programming, and weak dynamic types. As a scripting language, script-based applications can be easily customized.Program. This article introduces the C-language-based JavaScript Engine spidermonkey, and discusses in detail how to use this engine to allow interaction between the C language and the Javascript language.

Mark this article!

Release date:February 17, 2011
Level:Elementary
Access status7621 views
Suggestion:0 (Add Comment)

Average score (7 in total)

Basic knowledge

Introduction to spidermonkey

Like other Javascript Engines, spidermonkey does not directly provide objects such as Dom, but parse and execute javascworkflowCodeAnd garbage collection. Spidlermonkey is an open-source project under Mozilla. To use spidermonkey, You need to download its source code and compile it into a static/dynamic library.

To use spidermonkey in your application, you must first understand the following three core concepts:

Runtime EnvironmentThe runtime environment is the space where all JavaScript variables, objects, scripts, and code context exist. Each context object and all objects exist here. Generally, an application only needs one runtime.

ContextContext refers to the script execution environment. In spidermonkey, the context can compile and execute scripts, access object attributes, call JavaScript Functions, convert types, and create/maintain objects. Almost all spidermonkey functions require context as their first parameter (jscontext *).

Context and thread are inseparable. Generally, a single-threaded application can use one context to complete all operations. Each context can only complete one operation at a time, only one thread can use context objects at a time. Generally, in a multi-threaded application, each thread corresponds to a context.

Global ObjectGlobal objects include all classes, functions, and variables used by JavaScript code. In Dom operations, we use:

 
Alter ("something ");

In fact, we use an alter attribute of the global variable window (this attribute is exactly a function). In fact, the preceding statement will not be interpreted:

 
Window. Alter ("something ");

Shows the relationship between the three elements:

Figure 1. engine internal structure dependency

Install spidermonkey

First download the source package js-1.7.0.tar.gz from the spidermonkey code library. This article is compiled in Linux environment, spidermonkey compilation and installation is very easy:

 
# Decompress tar xvzf js-1.7.0.tar.gz # Switch to the source directory CD js-1.7.0/src # compile make-F makefile. Ref

After compilation, a new directory is generated. The directory name depends on the platform. For example, in Linux, the directory name is linux_all_dbg.obj, which contains the static Link Library libjs. A and dynamic link library libjs. so. The subsequent compilation environment of this article depends on the library files compiled here. It should be noted that the library file compiled here contains debugging support and is large. When the application is released, you can remove these debugging support and re-compile the database using the following:

 
# Create a non-debug mode library make build_opt = 1-F makefile. Ref

Compilation on windows and other platforms is not described here. Readers can refer to the official spidermonkey documentation.

Conversion Relationship Between JavaScript objects and C objects

Javascript is a weak type language. The type of the variable value is determined at runtime, and can be changed to another type of variable at runtime. C language, it is a static language, and the variable type has been determined during compilation. Therefore, it is difficult to exchange variables between the two. spidermonkey provides a common data type jsval to complete interaction between the two.

In fact, variables of the jsval type defined in the C code can be strings, numbers, objects, Boolean values, and null or undefined in JavaScript. Based on this type, spidermonkey provides a large number of types for judgment and type conversion macros and functions. See the following table:

Table 1. Conversion between JavaScript objects and C objects

Javascript type

Jsval type judgment

Jsval constant

Jsval Conversion

Null

Jsval_is_null (V)

Jsval_null

Undefined

Jsval_is_void (V)

Jsval_void

Boolean

Jsval_is_boolean (V)

Jsval_true,

Jsval_false,

Boolean_to_jsval (B)

Jsval_to_boolean (V)

Number

Jsval_is_number (V ),

Jsval_is_int (V ),

Jsval_is_double (V)

Int_to_jsval (I ),

Double_to_jsval (d)

Jsval_to_int (V ),

Jsval_to_double (V)

String

Jsval_is_string (V)

String_to_jsval (s)

Jsval_to_string (V ),

Js_getstringchars (s ),

Js_getstringlength (s)

Object

Jsval_is_object (V)

& Jsval_is_null (V)

Object_to_jsval (o)

Jsval_to_object (V)

It should be noted that jsval has certain defects:

    • Jsval is not completely type-safe. Before type conversion, you must specify the True Type of the converted object. For example, if the value of a variable is of the number type, the conversion from string to string may cause program crash. The solution is to make a judgment before conversion.
    • Jsval is the main target of spidermonkey's garbage collection mechanism. If jsval references a javascript object, but the Garbage Collector cannot know this, once the object is released, jsval will reference a floating pointer. This can easily cause program crash. The solution is to explicitly notify the garbage collector when the JavaScript Object is referenced.

Back to Top

Simple Example

Basic Code Template

Basic Process

The following process is generally used to use spidermonkey:

    • Create Runtime Environment
    • Create one or more context objects
    • Initialize a Global Object
    • Execute the script to process the result
    • Release engine Resources

Each process is described in the next section.

Code Template

With spidermonkey, some code is used by almost every application, such as error reports, runtime environment initialization, context, global variables, and global variables instantiation. Here is a typical template:

List 1. Required header files

 
# Include "jsapi. H"

Introduce jsapi. h. Declare the mark, struct, and function signature used in the engine. This is the only interface file required to use spidermonkey (of course, jsapi. it is impossible to define all interfaces in H. These files are stored in jsapi. introduce jsapi to the H header. h. If you are not familiar with the C language interface and header file introduction method, refer to relevant materials ).

List 2. Global variable Declaration

/* Global variable class declaration */static jsclass global_class = {"Global", role, js_propertystub, role, role, js_convertstub, role, role };

Jsclass is an important data structure that defines the basic structure of JavaScript objects-"class". This class can be instantiated as an object through the spidermonkey engine. Js_propertystub is a variable of the js_propertyop type. Here, js_propertystub is used to provide a default value. Js_propertyop can be used as the setter/getter of the object. The content will be discussed in detail in later sections.

Listing 3. error handling functions

 
/* Error handling function, used for callback and Printing Details */void report_error (jscontext * CX, const char * message, jserrorreport * Report) {fprintf (stderr, "% s: % u: % s \ n ", Report-> filename? Report-> filename: "<no FILENAME>", (unsigned INT) Report-> lineno, message );}

After defining these structures, we need to instantiate these structures to make them memory objects. The process is as follows:

Listing 4. Main Process

Int main ( Int Argc, Char * Argv []) {jsruntime * runtime; jscontext * context; jsobject * Global; // create a new runtime 8 m runtime = js_newruntime (8l * 1024l * 1024l ); if (runtime = NULL ){ Return -1;} // create a new context = js_newcontext (runtime, 8*1024 ); If (Context = NULL ){ Return -1;} // js_setoptions (context, jsoption_varobjfix); // set the error callback function. The report_error function is defined as js_seterrorreporter (context, report_error ); // create a new JavaScript Object global = js_newobject (context, & global_class, null, null ); If (Global = NULL ){ Return -1;} // instantiate global and add objects and arrays. If (! Js_initstandardclasses (context, global )){ Return -1;} // use global, context, and so on to complete other operations. The user-defined code starts from this. // release the context object js_destroycontext (context ); // release the runtime environment js_destroyruntime (runtime); // stop the JS Virtual Machine js_shutdown (); Return 0 ;}

The user's own code starts from the comments section in the middle of the above Code. The user code can use the context object here and the Global Object with predefined attributes and methods.

Execute JavaScript code

Execute JavaScript code snippets

The simplest way to execute JS is to give the script as a string to the engine for interpretation and execution, and release a temporary script object after the execution is complete. Spidermonkey provides a js_evaluatescript function. The prototype is as follows:

Listing 5. function prototype for executing JS Code

 
JsboolJs_evaluatescript(Jscontext * CX, jsobject * OBJ,Const char* SRC, uintn length,ConstChar* Filename, uintn lineno, jsval * rval );

To use this function, you must provide context, global variables, string scripts, script length, and return value pointers. The Script Name and line number parameters can be left blank (null and 0 respectively ). If the function returns js_true, the execution is successful and the execution result is stored in the rval parameter. Otherwise, the execution fails and the value in rval is undefined. Here is an example:

Listing 6. Execute js code snippets

 
Char* Script = "(function (a, B) {return a * B;}) (15, 6);"; jsval rval; status = js_evaluatescript (context, global, script, strlen (SCRIPT) \, null, 0, & rval );If(Status = js_true) {jsdouble D; js_valuetonumber (context, rval, & D); printf ("eval result = % F \ n", d );}

The execution result is:

 
Eval result = 90.000000

Compile JavaScript code

Generally, we may execute a script multiple times. spidermonkey can compile the script into a jsscript object for subsequent calls. Let's look at an example. Use C code to compile a Javascript script and then run it.

Listing 7. load and execute scripts from a file

JsboolEvalscriptfromfile(Jscontext * cntext,ConstChar * file) {jsscript * script; jsstring * JSS; jsbool status; jsval value; // get the Global Object jsobject * Global = js_getglobalobject (context ); // compile the script for further using script = js_compilefile (context, global, file );If(Script = NULL ){ReturnJs_false;} // execute it once status = js_executescript (context, global, script, & value); JSS = js_valuetostring (context, value); printf ("eval script result is: % s \ n ", js_getstringbytes (JSS); // destory the script object js_destroyscript (context, script );ReturnStatus ;}

Passed to the FunctionEvalscriptfromfileThe jscontext * parameter of is the context object created externally. For the creation method, see the previous section.

Listing 8. Execution

Jsbool status = evalscriptfromfile (context, "jstest. js ");If(Status = js_false) {fprintf (stderr, "error while evaluate the script \ n ");}

Suppose we save the following script content into a script jstest. JS:

Listing 9. jstest. js script content

 
VaRPerson =Function(Name) {VaR _ name _ = Name; this. getname = function (){Return_ Name _;}This. Setname =Function(Newname) {_ name _ = newname ;}}VaRJack =NewPerson ("Jack"); Jack. setname ("John"); // The last sentence returns the execution result of the script to C code Jack. getname ();

The name of the jack object is now set to "John". The value of the last statement of the script will be returned to the C code as the return value of the script and printed out:

 
Eval script result is: John

Back to Top

Interaction between C and JavaScript

C program calls JavaScript Functions

Because of the large differences in data types between the two, JavaScript code cannot be called directly from the C code, and some conversions are required, to convert the C variable to Javascript, you can set another variable type, and then pass the parameter. The return value must also be converted.

We define a function add in Javascript. This function accepts two parameters and returns the sum of the two parameters passed in. Definition:

Listing 10. Add of the Javascript version

 
FunctionAdd (x, y ){ReturnX + Y ;}

Then, we call this JS function by name in the C language:

Listing 11. calling Javascript functions from C code

JsboolFunc_test(Jscontext * context) {jsval res; jsobject * Global = js_getglobalobject (context); jsval argv [2]; // new 2 number to pass into the function "add" in script js_newnumbervalue (context, 18.5, & res); argv [0] = res; js_newnumbervalue (context, 23.1, & res); argv [1] = res; js_callfunctionname (context, global, "add", 2, argv, & res); jsdouble D; // convert the result to jsdouble js_valuetonumber (context, res, & D); printf ("add result = % F \ n", d );ReturnJs_true ;}

Note that the parameter list of the js_callfunctionname function is as follows:

Listing 12. Prototype of js_callfunctionname

 
Jsbool js_callfunctionname (jscontext * CX, jsobject * OBJ, const char * Name, uintn argc, jsval * argv, jsval * rval );

Table 2. Meaning of the js_callfunctionname parameter list

Name

Type

Type description

CX

Jscontext *

Context Definition

OBJ

Jsobject *

The object that calls this method.

Name

Const char *

Function Name

Argc

Uintn

Number of function parameters

Argv

Jsval *

Array formed by the actual function parameters

Rval

Jsval *

Return Value

Argv In the parameter is an array formed by jsval. If a value of the C type is directly transferred, core dump (caused by a segment error in Linux) may easily occur. Therefore, the js_newnumbervalue function is required to convert double to number in C language (for the reason, see the object conversion section ).

Javascript programs call c Functions

Calling C functions in JS is complicated compared with the previous section. Let's look at an interesting example: the global variables of JavaScript originally generated in spidermonkey do not contain the print function, we can use C's printf to implement this function. We have defined a function print that uses the logging function, while the logging function is defined in C language. It accepts a string as a parameter and prints the string to the standard output:

Listing 13. Javascript calls c Functions

 
// Log user log in Information logging ("User Jack login on 2010/7/6"); // user do nothing else nothing (); // log user log out information logging ("User Jack logout on 2010/7/7 ");FunctionPrint () {(VaRI = 0; I <arguments. length; I ++) {logging (arguments [I]) ;}} print ("hello", "all", "my", "friend ");

In the C language, we define the prototype of the logging function and the nothing function as follows:

Listing 14. Implementation of c Functions

/*** Define an exposed function to be used in scripts * print out all the incoming arguments as string. */static jsbool logging (jscontext * context, jsobject * object, uintn argc, jsval * argv, jsval * value ){IntI = 0; jsstring * JSS;For(I = 0; I <argc; I ++) {JSS = js_valuetostring (context, argv [I]); printf ("Message from script environment: % s \ n ", \ js_getstringbytes (JSS ));}ReturnJs_true;}/*** define an exposed function to be used in scripts * do nothing but print out a single line. */static jsbool nothing (jscontext * context, jsobject * object, uintn argc, jsval * argv, jsval * value) {printf ("Got nothing to do at all \ n ");ReturnJs_true ;}

From the signature of the function, we can see that the return values of the functions exposed to JS in C, the number of parameters, and the type at the corresponding position are fixed. All functions exposed to JS from C need to "implement this interface ".

After you have defined the functions, you need some other settings to use these functions in Js. First define an array of the jsfunspec spec type, and then place these functions on the global object through js_definefunctions. Then, you can access the C functions listed above in JS Code. The procedure is as follows:

Listing 15. register the function list

 
StaticJsfunctionspec functions [] = {"logging", logging, log_minargs, 0, 0}, {"nothing", nothing, not_minargs, 0, 0}, {0, 0, 0, 0, 0, 0 }}; // define function list hereIf(! Js_definefunctions (context, global, functions )){Return-1 ;}

The running result is as follows:

 
Message from script environment: User Jack login on 2010/7/6 got nothingDoAt all message from script environment: User Jack logout on 2010/7/7 message from script environment: Hello Message from script environment: All message from script environment: My message from script environment: Friend

Define JavaScript objects in C Programs

In spidermonkey, it is complicated to use objects defined by the C language in Javascript. Once we can define objects, the interaction between the two worlds through javascript becomes very simple and interesting, it is easy to use this method to customize our applications. After the system is released, you can easily modify the system behavior.

First, we need to define the basic data structure, that is, the attributes and structure of the objects we want to expose to the JS world. Then, we need to use jsapi to define the attributes of this object. Then, use jsapi to define the method of the object. Finally, create the object, bind its attribute table and method list, and put it into the global object.

Suppose we have a data structure to express a person's simple information:

Listing 16. persioninfo Structure

 
Typedef struct {char name [32]; char ADDR [128];} personinfo;

Define an attribute table as an enumeration type:

Listing 17. Attribute Table

 
EnumPerson {Name,Address};

We need to define the native data structure of the C language as recognized by the jsapi:

Listing 18. Attribute Definition

 
// Define person properties jspropertyspec pprops [] = {"name ",Name, Jsprop_enumerate}, {"Address ",Address, Jsprop_enumerate}, {0 }};

Listing 19. method definition

// Define person Methods jsfunctionspec pfuncs [] = {"print", printing, 0}, {"getname", getname, 0}, {"setname", setname, 0 },{ "getaddress", getaddress, 0 },{ "setaddress", setaddress, 0 },{ 0 }};

Listing 20. Class Definition

 
// Define person class (jsclass) jsclass Pclass = {"person", 0, js_propertystub, role, role, js_convertstub, role };

Once these basic information is defined (the implementation of getter/setter in the pfuncs array is relatively simple, because the code is not listed here, interested friends can refer to the appendix), we can instantiate it, and put it into the context so that JS Code can be accessed.

Listing 21. Defining attributes and methods of Objects

Jsobject * person; // define the object person = js_defineobject (\ context, global, "person", & Pclass, 0, jsprop_enumerate ); // install the properties and methods on the person object js_defineproperties (context, person, pprops); js_definefunctions (context, person, pfuncs );

In this way, in JavaScript code, we can use the person identifier to access the person object:

Listing 22. Test script

 
// Undefined Of course person. print (); // person. name = "Abruzzi"; // person. address = "Huang Quan Road"; person. setname ("desmond"); person. setaddress ("huangquan Road"); // print is global function, access properties directly print ("person name =" + person. name); print ("person address =" + person. address); person. print ();(Function() {// Using getter/setter to access PropertiesReturnPerson. getname () + ":" + person. getaddress ();})();

The running result is as follows:

Name:UndefinedAddress:UndefinedPerson Name = Desmond person address = huangquan road name: Desmond address: huangquan road eval script result is: Desmond: huangquan Road

Back to Top

Conclusion

This article discusses in detail how to use the C-based JavaScript Engine: spidermonkey usage. Including the most basic code templates, interaction between C code and JavaScript code, and defining JavaScript objects in C code, it is easy to script the application. In practical applications, some components of an application (provided to user-defined components) can be exposed to JavaScript for access, or provide function stubs in JavaScript scripts (just define the prototype of the function). You can implement the specific logic of these functions to implement scripting.

Back to Top

Download

Description

Name

Size

Download Method

Sample Code

Jsfun.zip

8 KB

HTTP

Information about the Download Method

References

Learning

    • Official spidermonkey website, including API function signature and complete documentation.
    • W3C's simple JavaScript tutorial introduces the basic usage of JavaScript on the client side.
    • This article describes the basic usage of spidermonkey.
    • In the developerworks Linux area, find more references for Linux developers (including new Linux beginners) and refer to our most popular articles and tutorials.
    • Read all Linux tips and Linux tutorials on developerworks.
    • Stay tuned to developerworks technical events and network broadcasts.

Discussion

    • Welcome to the developerworks Chinese community.

About the author

Qiu Juntao graduated from Kunming University of Science and Technology in computer science and technology. He is interested in mechanical control, electronics, artificial intelligence, functional programming, and other fields, familiar with the underlying computer science. C, Java, Python, JavaScript, and other languages are preferred. He is now at the cloud power Tongfang R & D center.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.