Google V8 Script Engine 使用体验
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 ...
如果借助宏,就较简单:
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(); 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/v8/
http://code.google.com/p/cproxyv8/