1, 导出全局函数到脚本环境
// v8test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <v8.h> #pragma comment(lib, "v8_base.lib") #pragma comment(lib, "v8_snapshot.lib") #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "winmm.lib") using namespace v8; // 在宿主环境中实现一个常规的println()函数 v8::Handle<v8::Value> HostPrint(const v8::Arguments& args) { for (int i = 0; i < args.Length(); i++) { v8::HandleScope handle_scope; // 转换成字符串用于打印 v8::String::AsciiValue str(args[i]); printf("%s", *str); } printf("\n"); // 返回Undefined, 类似于返回void return v8::Undefined(); } int main(int argc, char* argv[]) { // Create a stack-allocated handle scope. HandleScope handle_scope; // 创建一个全局模板用于修改脚本对象 v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); // 把宿主的HostPrint函数注册到脚本环境 globalTemplate->Set(v8::String::New("println"), v8::FunctionTemplate::New(HostPrint)); // Create a new context. v8::ExtensionConfiguration * extConfig = NULL; // 并且把自定义的全局模板globalTemplate作为参数传入 Handle<Context> context = Context::New(extConfig, globalTemplate); // 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("" "println('Hello ', 'world ', 1, ' ', 2, ' ', Math.PI);" // 在脚本环境中调用宿主函数 "" ); String * str = *source; // 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. (Persistent<Context>(context)).Dispose(); return 0; }
2, 运行结果:
Hello world 1 2 3.141592653589793 请按任意键继续. . .
3, 导出静态变量到脚本环境
// v8test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <v8.h> #pragma comment(lib, "v8_base.lib") #pragma comment(lib, "v8_snapshot.lib") #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "winmm.lib") using namespace v8; // 在宿主环境中定义一个全局变量 static int globalVarInV8Host = 0; static Handle<Value> XGetter(Local<String> key,const AccessorInfo& info) { return Integer::New(globalVarInV8Host); } static void XSetter(Local<String> key, Local<Value> value,const AccessorInfo& info) { globalVarInV8Host = value->Int32Value(); } // 在宿主环境中实现一个常规的println()函数 v8::Handle<v8::Value> HostPrint(const v8::Arguments& args) { for (int i = 0; i < args.Length(); i++) { v8::HandleScope handle_scope; // 转换成字符串用于打印 v8::String::AsciiValue str(args[i]); printf("%s", *str); } printf("\n"); // 返回Undefined, 类似于返回void return v8::Undefined(); } int main(int argc, char* argv[]) { // Create a stack-allocated handle scope. HandleScope handle_scope; // 创建全局模板globalTemplate v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); // 注册globalVarInV8Host变量的访问器 globalTemplate->SetAccessor(v8::String::New("globalVarInV8Host"), XGetter, XSetter); // 为了查看变量,把HostPrint也注册进去 globalTemplate->Set(v8::String::New("println"), v8::FunctionTemplate::New(HostPrint)); // Create a new context. Handle<Context> context = Context::New(NULL, globalTemplate); // 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("" "var v1 = globalVarInV8Host;" "v1 = 100;" "println('v1=', v1, ';', 'globalVarInV8Host=', globalVarInV8Host);" "var v2 = globalVarInV8Host;" "v2 = 200;" "println('v2=', v2, ';', 'globalVarInV8Host=', globalVarInV8Host);" "globalVarInV8Host = 300;" "println('v1=', v1, ';', 'v2=', v2, ';', 'globalVarInV8Host=', globalVarInV8Host);" ); String * str = *source; // 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. (Persistent<Context>(context)).Dispose(); return 0; }
4, 运行结果:
v1=100;globalVarInV8Host=0 v2=200;globalVarInV8Host=0 v1=100;v2=200;globalVarInV8Host=300 请按任意键继续. . .
5, 导出动态对象到脚本环境
// v8test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <v8.h> #pragma comment(lib, "v8_base.lib") #pragma comment(lib, "v8_snapshot.lib") #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "winmm.lib") using namespace v8; // 在宿主环境中实现一个常规的println()函数 v8::Handle<v8::Value> HostPrint(const v8::Arguments& args) { for (int i = 0; i < args.Length(); i++) { v8::HandleScope handle_scope; // 转换成字符串用于打印 v8::String::AsciiValue str(args[i]); printf("%s", *str); } printf("\n"); // 返回Undefined, 类似于返回void return v8::Undefined(); } // 定义一个简单的c++类 class CUser { public: int uid_; public: CUser(int uid) : uid_(uid){ } virtual ~CUser() { } static Handle<Value> GetUID(Local<String> property, const AccessorInfo &info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); int value = static_cast<CUser*>(ptr)->uid_; return Integer::New(value); } static void SetUID(Local<String> property, Local<Value> value, const AccessorInfo& info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); static_cast<CUser*>(ptr)->uid_ = value->Int32Value(); } }; /** * Utility function that wraps a C++ object in a * JavaScript object. * 封装c++对象成为一个js对象 */ Handle<Object> WrapUserObject(CUser * pUser) { // Handle scope for temporary handles. HandleScope handle_scope; Handle<ObjectTemplate> templ = ObjectTemplate::New(); // 设置内部插槽个数为1,分配一个内部存储区域 templ->SetInternalFieldCount(1); // 设置访问器 templ->SetAccessor(String::New("uid"), CUser::GetUID, CUser::SetUID); // Create an empty http request wrapper. Handle<Object> result = templ->NewInstance(); // Store the request pointer in the JavaScript wrapper. result->SetInternalField(0, External::New(pUser)); // Return the result through the current handle scope. Since each // of these handles will go away when the handle scope is deleted // we need to call Close to let one, the result, escape into the // outer handle scope. return handle_scope.Close(result); } int main(int argc, char* argv[]) { // Create a stack-allocated handle scope. HandleScope handle_scope; // 创建全局模板globalTemplate v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); // 为了查看变量,把HostPrint也注册进去 globalTemplate->Set(v8::String::New("println"), v8::FunctionTemplate::New(HostPrint)); // Create a new context. Handle<Context> context = Context::New(NULL, globalTemplate); // Enter the created context for compiling and // running the hello world script. Context::Scope context_scope(context); // 创建一个本地对象 CUser * pUser = new CUser(12345); // 封装成一个JS脚本对象 Handle<Object> userObject = WrapUserObject(pUser); // 使用以下方式注册user对象到全局范围 context->Global()->Set(String::New("user"), userObject); // 以下方式是错误的, TODO: 全局对象和代理(proxy)全局对象的区别 // http://bespin.cz/~ondras/html/classv8_1_1Context.html // https://wiki.mozilla.org/Gecko:SplitWindow // globalTemplate->Set(String::New("user"), userObject); // Create a string containing the JavaScript source code. Handle<String> source = String::New("" "println(user.uid);" ); String * str = *source; // 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. (Persistent<Context>(context)).Dispose(); return 0; }
6, 运行结果
12345 请按任意键继续. . .
7, 参考:
https://code.google.com/p/cproxyv8/wiki/Usage
http://iammr.7.blog.163.com/blog/static/49102699201201565822189/
https://developers.google.com/v8/embed
https://wiki.mozilla.org/Gecko:SplitWindow
http://bespin.cz/~ondras/html/classv8_1_1Context.html