分类: Windows平台
2017-03-31 10:53:06
1. C++类
claa Person
{
int m_nAge;
char m_scName[128];
public:
Person(int age, const char* scName) : m_nAge(age){
memcp(m_scName, scName, strlen(scName));
}
int age(){ return m_nAge; }
void setAge(int nAge){m_nAge = nAge; }
const char *name(){ return m_scName;}
void setName(const char *scName){
memcpy(m_scName, scName, strlen(scName);
}
void showInfo(){
char scBuffer[512] = {0};
sprintf(scBuffer, 512, "His name is %s, and %d years old", m_scName, m_nAge);
}
}
2. 调用准备
1) 构造函数
void newPerson(const FunctionCallbackInfo& args){
if (args.Length() != 2) { // the two parameters are age and name
args.GetReturnValue().Set(false);
return;
}
// parameters ready
Local age_val = args[0]; // the age value
Local name_val = args[1]; // the name value
int nAge = age_val->ToInt32(context).ToLocalChecked()->Value();
String::Utf8Value scName(name_val);
Person *pPerson = new Person(nAge, *scName);
///////////////////////////////////
// 下面比较重要
// 定义一个本地外部变量,和pPerson关联
Local
// 定义一个全局外部变量和本地外部变量关联
Global
// 设置析构函数(测试半天,好像没有用,暂时先放到这儿)
ret.SetWeak((void *)pCardReader, deletePerson, WeakCallbackType::kFinalizer);
// 将全局外部变量和JS脚本的内容关联起来
args.Holder()->SetInternalField(0, ret.Get(pIsolate));
////////////////////////////////////////
args.GetReturnValue().Set(true);
}
2) 析构函数
void deletePerson(const WeakCallbackInfo
{
void * pParameter = data.GetParameter();
if (Person *pPerson = static_cast
delete pPerson;
}
}
3) 类的可使用属性接口(在JS中可以使用的类变量/方法)
// 使用Person类的showInfo方法
void showInfoCallBack(const FunctionCallbackInfo
{
// 获取JS脚本中的类的实例
Local
// 通过该实例获取new Person出来的类实例(本地类实例)
Local
if (Person*pPerson = static_cast
pPerson->showInfo();
}
return;
}
// 使用Person类的int age属性(变量必须包括两个方法Get/Set)
void getAge(Local
{
// 获取JS内部实例对象
Local
// 通过内部实例的内部域获取本地外部例对象
Local
// 通过本地外部对象获取Person的本地实例
void* ptr = wrap->Value();
int value = static_cast
info.GetReturnValue().Set(value);
}
void setAge(Local
{
Local
Local
static_cast
}
4) 建立C++类(Person)的ObjectTemplate
void createPersonObjectTemplate(Isolate* isolate, Local
{
HandleScope handle_scope(isolate);
// JS脚本中C++类的名称(new XXX)
Local
// 类Person的模板,关联构造函数
Local
// 设置类名称
cPersonTpl->SetClassName(scClassName);
// 为JS脚本对象设置内部域的个数(这个知道怎么用,但是不是很清楚为什么),在这儿用来保存本地实例指针(在构造函数中new的实例)
cPersonTpl->InstanceTemplate()->SetInternalFieldCount(1);
///////////////////////////////////////////////////////////////////
// 设置C++类在JS脚本中的属性模板,并不是说C++中的所有属性都共享给JS。在这儿是将(2-3)类可使用属性和类模板的属性模板关联起来
// 获取类模板的属性模板
Local
// 设置Person::m_nAge属性
person_proto->SetAccessor(
String::NewFromUtf8(isolate, "nAge", NewStringType::kInternalized).ToLocalChecked(),
getAge, setAge);
// Person::showInfo方法属性
Person_proto->Set(
String::NewFromUtf8(isolate, "showInfo", NewStringType::kInternalized).ToLocalChecked(),
FunctionTemplate::New(isolate, showInfoCallBack));
// 将Person类模板通过类名称挂在一个全局(作用域)的对象模板下
global->Set(scClassName, cPersonTpl);
return;
}
5) 全局对象模板被挂靠在全局上下文(context)下
{
// Create a handle scope to hold the temporary references.
HandleScope handle_scope(GetIsolate());
// Create a template for the global object where we set the
// built-in global functions.
Local
createPersonTemplate(GetIsolate(), global);
// Each processor gets its own context so different processors don't
// affect each other. Context::New returns a persistent handle which
// is what we need for the reference to remain after we return from
// this method. That persistent handle has to be disposed in the
// destructor.
v8::Local
context_.Reset(GetIsolate(), context);
// Enter the new context so all the following operations take place
// within it.
Context::Scope context_scope(context);
...
}
3. 在JS脚本中使用
var person = new Person(28, "Jerry");
person.showInfo();