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