JavaScript is a widely used scripting language for Web client development, often used to control the browser's DOM tree and add dynamic functionality to HTML pages. The Web standard that JavaScript adheres to today is ECMAScript262. Because JavaScript provides rich built-in functions, good object mechanics. JavaScript can also be embedded in a host language to compensate for the expressiveness of the host language, enabling rapid, flexible, and customizable development.
Software program application JavaScript
The existing mainstream browsers have basically implemented a JavaScript engine of their own. These JavaScript engines can parse, compile, and execute JavaScript scripts. These JavaScript engines are written in C or C + + and provide API interfaces externally. So using these JavaScript engines in C and C + + languages is handy for embedding JavaScript. There are some well-known open source projects that use this approach for mixed programming, such as node. js, K-3d, and so on.
The known-famous JavaScript engine has Google's V8 engine, IE's Trident engine, Firefox's SpiderMonkey engine, WebKit's JavaScriptCore engine, opera's Carakan engine (non-open source , this article does not analyze) and so on. The API interfaces provided by these JavaScript engines are different in detail, but a basic design concept for these APIs is similar. C, C + + to use these engines, first of all to obtain a global object. This global object has properties, methods, and events. For example, there is a Window object in the JavaScript environment. It describes a browser window. In general JavaScript to refer to its properties and methods, it is not necessary to use "window.xxx" in this form, but directly using "XXX". It is the largest object in JavaScript, all other JavaScript objects, functions, or sub-objects of it, or child objects. C, C + + can achieve bidirectional interaction with JavaScript by invoking get, set operations on the largest global object.
V8 External API interface is the interface of C + +. The V8 API defines several basic concepts: handle (handle), scope (scope), context. Templates (Templates) to understand these basic concepts before you can use V8.
Contextual context is the environment in which scripts are run, and JavaScript variables, functions, and so on are present in context contexts. Context can be nested, that is, the current function has a context, when invoking other functions if there is a context, then in the function called JavaScript is the most recent context, when exiting the function, and return to the original context.
The L handle (handle) is a pointer to a V8 object, a bit like a smart pointer to C + +. All V8 objects must be manipulated using a handle. There are no V8 objects that the handle points to, and will soon be reclaimed by the garbage collector.
L scope (scope) is the container of a handle, and a scope (scope) can have many handles (handle). When you leave a scope (scope), all the handles (handle) in scope (scope) will be freed.
The L template (Templates) is divided into function templates and object templates, and is the encapsulation of V8 functions and objects for JavaScript. Functions and objects that facilitate the operation of JavaScript in the C + + language.
The L V8 API defines a set of classes or templates that correspond to the language concept of JavaScript one by one. Like what:
V8 function templates correspond to JavaScript functions
V8 object classes correspond to JavaScript objects
The string class of V8 corresponds to the character of the JavaScript
The script class of V8 corresponds to the scripting text of JavaScript, which compiles and executes a script.
2.2. C + + call JavaScript
Using V8 to access the contents of a JavaScript script in C + +, First call context::getcurrent ()->global () to get to the global Globals object. The global variables, global functions, and global complex objects are extracted by the Get function of global objects. Examples of C + + code are:
Get Global Object
HandleGlobalobj = Context::getcurrent ()->global ();
Get Javascrip Global Variables
Handle value = Globalobj->get (String::new ("JavaScript variable name"));
INTN = value->toint32 ()->value ();
Gets the Javascrip global function and calls the global function
Handle value = Globalobj->get (String::new ("JavaScript function name"));
Handle func = Handle:: cast (value);//Convert to function
Local v1 = int32::new (0);
Local<Value> v2 = Int32::New(1);
Handle Args[2] = {v1, v2}; function parameters
Func->call (Globalobj, 2, args);
Gets the Javascrip global object and calls the object's function
Handle value = Globalobj->get (String::new ("JavaScript complex object name"));
Handleobj = Handle:: Cast (value);//Convert to complex object
Handle Objfunc = obj->get (string::new ("JavaScript object Function name"));
Handle args[] = {string::new (' callobject function ')};//function parameters
Objfunc->call (globalobj, 1, args);
2.3. JavaScript calls C + +
Using V8, in JavaScript scripts to access content in C + +, you must first inject C + + variables, functions, and classes into Javacsript. Injection, first call context::getcurrent ()->global () to get to the global object, and then through the global object's set function to inject global variables, global functions, class objects.
The injection process of global variables and global functions is similar to the code in the previous section, where it is omitted. The trouble is to inject C + + classes and class objects into JavaScript. Its basic process is as follows:
Define a C + + class First, define a class object pointer
Defines a set of C + + global functions that encapsulate V8 calls to C + + classes that are provided to V8 for callback callbacks.
Finally, call the V8 API to inject the defined C + + classes and C + + functions into JavaScript
In V8 's API interface, an "internal data" (Internal Field) concept is provided, and "internal data" is a void pointer that allows V8 objects to hold a C + + . When V8 callback the C + + global function, C + + can set or get the void pointer.
The following is an example of C + + code that injects C + + classes, class variables into JavaScript.
A C + + class test,
Class Test
{
Public
test(){number=0;};voidfunc(){number++;}int number;
};
A Global object G_test
The goal is to use this object directly in JavaScript, such as G_test.func ()
Test g_test;
Encapsulating V8 calling the test class constructor
In JavaScript if executed: var t = new test; V8 will call this C + + function
This function is also called when executing the Newinstance function injection object in C + +
The default test class's constructor has no arguments, and an additional parameter is provided when C + + injects an object
V8::handle TestConstructor (constv8::arguments& args)
{
v8::Local<v8::Object>self = args.Holder();//这里假定有两个“内部数据”(Internal Field)//第一个“内部数据”保存test对象的指针//第二个“内部数据”为1 就表示这个对象是由C++注入的//第二个“内部数据”为0 就表示这个对象是JS中自己建立的if(args.Length()){ //默认为0,当C++注入对象时,会填充这个“内部数据” self->SetInternalField(0,v8::External::New(0)); self->SetInternalField(1,v8::Int32::New(1));}else{ self->SetInternalField(0,v8::External::New(new test)); self->SetInternalField(1,v8::Int32::New(0));}return self;
}
Encapsulating V8 Calling the test class Func method
In JavaScript if executed: T.func (); V8 will call this C + + function
V8::handle TestFunc (constv8::arguments& args)
{
//获取构造函数testConstructor时,设置的对象指针v8::Local<v8::Object>self = args.Holder();
V8::local Wrap =v8::local:: Cast (Self->getinternalfield (0));
void* ptr =wrap->Value();//调用类方法static_cast<test*>(ptr)->func();returnv8::Undefined();
}
Encapsulate V8 Call test class member variable number
In JavaScript if executed: T.number; V8 will call this C + + function
V8::handle Gettestnumber (v8::local property, const v8::accessorinfo& info)
{
//获取构造函数testConstructor时,设置的对象指针v8::Local<v8::Object>self = info.Holder();
V8::local Wrap =v8::local:: Cast (Self->getinternalfield (0));
void* ptr =wrap->Value();//返回类变量returnv8::Int32::New(static_cast<test*>(ptr)->number);
}
After the C + + class and global functions are well defined, you can begin to inject classes, variables into V8 JavaScript.
Get Global Object
V8::handle globalobj =context->global ();
Create a new function template, TestConstructor is the global function defined above
V8::handle Test_templ =v8::functiontemplate::new (testconstructor);
Set class name
Test_templ->setclassname (v8::string::new ("Test"));
Get prototype,
V8::handle Test_proto =test_templ->prototypetemplate ();
Add the class member function, TestFunc is the global function defined above
Test_proto->set ("Func", V8::functiontemplate::new (TestFunc));
Sets two internal data that holds a pointer to the class object when the TestConstructor is used to construct the function.
V8::handle test_inst =test_templ->instancetemplate ();
Test_inst->setinternalfieldcount (2)
Adding class member variables
Gettestnumber is the global function defined above
Only the get operation of the member variable is provided, and the last parameter is the set operation of the member variable, which omits the
Test_inst->setaccessor (V8::string::new ("number"), Gettestnumber, 0);
Inject the definition of the test class into JavaScript
V8::handle point_ctor =test_templ->getfunction ();
Globalobj->set (v8::string::new ("test"), Point_ctor);
Creates a new test object and causes G_test to bind the newly created object
V8::handle flag = v8::int32::new (1);
V8::handle obj =point_ctor->newinstance (1, &flag);
Obj->setinternalfield (0, V8::external::new (&g_test));
Globalobj->set (V8::string::new ("G_test"), obj);
When you inject C + + classes and class pointers into V8 JavaScript, you can use them in javascript:
G_test.func ();
var n = g_test.number;
var t = new test;
End.
The JavaScript engine is called in c,c+