Google V8 JavaScript Engine是google为 Chrome's浏览器开发的脚本引擎,现在可以使用V8 JavaScript Engine在C++程序中建立自己的脚本环境。
1.准备工作
1). 安装一个SVN客户端 http://tortoisesvn.net/downloads,google v8 在官方网站仅以此方式发布;
2).下载一个python:地址http://sourceforge.net/projects/pywin32/files/,官方网站2009年10月15日被墙了
2.checkout并准备环境
0)设置目录:
+third_party
+python_24 Python位置(拷贝或安装到均可)
+V8 V8 check out 位置
1)安装python
---------------------------------------begin-------------------------------------------------
说明:
由于v8.project在配置时,使用如下命令进行处理:
.\d8js2c.cmd ..\..\src "$(IntDir)\DerivedSources"
其中: d8js2c.cmd(line4): set PYTHON="..\..\..\third_party\python_24\python.exe"
显然python和相关库应该位于:..\..\..\third_party\python_24\
---------------------------------------end---------------------------------------------------
2)下载 Google V8 Script Engine下载,
SVN地址: http://code.google.com/p/v8/source/checkout
3)编译
V8\tools\visual_studio\v8.sln
这样就可以编译了,如果编译失败,那可能就是python没有配置好。
3. JS 嵌入C++示例代码
一个Hello world!
#include "http://www.cnblogs.com/include/v8.h"
#pragma comment(lib,"../visual_studio/Release/lib/v8.lib")
#pragma comment(lib,"../visual_studio/Release/lib/v8_base.lib")
using namespace v8;
int main(int argc, char* argv[]) {
// Create a stack-allocated handle scope.
HandleScope handle_scope;
// Create a new context.
Persistent<Context> context = Context::New();
// Enter the created context for compiling and
// running the hello world script.
Context::Scope context_scope(context);
// Create a string containing the JavaScript source code.
Handle<String> source = String::New("'Hello' + ', World!'");
// Compile the source code.
Handle<Script> script = Script::Compile(source);
// Run the script to get the result.
Handle<Value> result = script->Run();
// Dispose the persistent context.
context.Dispose();
// Convert the result to an ASCII string and print it.
String::AsciiValue ascii(result);
printf("%s\n", *ascii);
return 0;
}
更多示例代码参考:V8\test\cctest\*.cc
4.支持C++类
CProxyV8提供便利的方式将C++类的属性和方法导出到JavaScript环境中。支持generic Functors,不需要为每个属性和方法设置回调函数。
class Point
{
public:
/** Constructor without params is required */
Point(int px = 0, int py = 0) : x_(px), y_(py) {}
Point(Point* p) : x_(p->x_), y_(p->y_) {}
int x_;
int y_;
/** Example call to function without params */
int GetManhattanLength() { return std::abs(x_) - std::abs(y_); }
/** this will create a JS object, with JS destructor */
Point* Copy() { return new Point(); }
/** Example call to function with params */
v8::Handle<v8::Value> Translate(const v8::Arguments& args)
{
// throw if we didn't get 2 args
if (args.Length() != 2)
return ThrowException(v8::String::New("Expected 2 arguments"));
x_ += args[0]->Int32Value();
y_ += args[1]->Int32Value();
return v8::True();
};
};
class Line
{
public:
/** Constructor without params is required */
/** Example of object property, it can be manipulate directly */
Point start;
/** this will create a JS object, without destructor and a reference to this
* end instance
*
*/
Point& GetEnd() { return end; }
private:
Point end;
};
int main(int argc, char* argv[])
{
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::HandleScope handle_scope;
// Create a template for the global object.
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
ProxyClass<Foo>* pPoint = ProxyClass<Foo>::instance(); //Get the proxy class for Point
pPoint->Expose(&Point::x_,"x",true,true); //expose x_ for read/write
pPoint->Expose(&Point::y_,"y",true,true); //expose y_ for read/write
pPoint->Expose(&Point::Copy, "copy");
pPoint->Expose(&Point::GetManhattanLength, "getManhattanLength");
pPoint->Expose(&Point::Translate, "translate");
ProxyClass<Line>* pLine = ProxyClass<Line>::instance(); //Get the proxy class for Line
pPoint->Expose(&Line::start,"start",true,true); //expose object start for read/write
pPoint->Expose(&Line::GetEnd, "getEnd");
global->Set(v8::String::New("Point"), pPoint->GetFunctionTemplate()); // add Point to JS
global->Set(v8::String::New("Line"), pLine->GetFunctionTemplate()); // add Line to JS
...
如果借助宏,就较简单:
// Create a template for the global object.
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
CPROXYV8_PROPERTY_ID(Point,x_,x,true,true);
CPROXYV8_PROPERTY_ID(Point,y_,y,true,true);
CPROXYV8_METHOD_ID(Point,Copy, copy);
CPROXYV8_METHOD_ID(Point,GetManhattanLength, getManhattanLength);
CPROXYV8_METHOD(Point,Translate);
CPROXYV8_PROPERTY(Line,start,true,true);
CPROXYV8_METHOD_ID(Line,GetEnd,getEnd);
global->Set(v8::String::New("Point"), CPROXYV8_CLASS(Point)->GetFunctionTemplate()); // add Point to JS
global->Set(v8::String::New("Line"), CPROXYV8_CLASS(Line)->GetFunctionTemplate()); // add Line to JS
在Shell中使用这些类:
V8 version 0.4.3.1
> x = new Point()
[object Point]
> line = new Line()
[object Line]
> x.x
0
> x.x = 10
10
> line.getEnd().x
0
> line.getEnd().x = 10
10
> line.getEnd().x
10
> end = line.getEnd();
[object Point]
> end.x
10
> end.Translate(10,10)
true
> end.x
20
> line.getEnd().x
20
> x.x
10
>_
官方网站:
http://code.google.com/p/cproxyv8/