Chinaunix首页 | 论坛 | 博客
  • 博客访问: 640296
  • 博文数量: 133
  • 博客积分: 1566
  • 博客等级: 上尉
  • 技术积分: 1230
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-01 09:31
文章分类

全部博文(133)

文章存档

2019年(1)

2018年(1)

2017年(8)

2016年(9)

2015年(17)

2014年(4)

2013年(31)

2012年(25)

2011年(36)

2010年(1)

我的朋友

分类: 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 external = External::New(pIsolate, (void*)pPerson);

 // 定义一个全局外部变量和本地外部变量关联

 Global ret(pIsolate, external);

 // 设置析构函数(测试半天,好像没有用,暂时先放到这儿)

 ret.SetWeak((void *)pCardReader, deletePerson, WeakCallbackType::kFinalizer);

 // 将全局外部变量和JS脚本的内容关联起来

 args.Holder()->SetInternalField(0, ret.Get(pIsolate));

 ////////////////////////////////////////

 args.GetReturnValue().Set(true);

}

2) 析构函数

void deletePerson(const WeakCallbackInfo& data)
{
 void * pParameter = data.GetParameter();
 if (Person *pPerson = static_cast(pParameter)) {
  delete pPerson;
 }
}

3) 类的可使用属性接口(在JS中可以使用的类变量/方法)

// 使用Person类的showInfo方法

void showInfoCallBack(const FunctionCallbackInfo& info)
{
  // 获取JS脚本中的类的实例
 Local obj = info.Holder();

 // 通过该实例获取new Person出来的类实例(本地类实例)
 Local wrap = Local::Cast(obj->GetInternalField(0)); 
 if (Person*pPerson = static_cast(wrap->Value())) {
   pPerson->showInfo();
 }
 return;
}

// 使用Person类的int age属性(变量必须包括两个方法Get/Set)

void getAge(Local key, const PropertyCallbackInfo& info)
{

 // 获取JS内部实例对象
 Local self = info.Holder();

 // 通过内部实例的内部域获取本地外部例对象
 Local wrap = Local::Cast(self->GetInternalField(0));

 // 通过本地外部对象获取Person的本地实例
 void* ptr = wrap->Value();
 int value = static_cast(ptr)->age();
 info.GetReturnValue().Set(value);
}

void setAge(Local key, Local value, const PropertyCallbackInfo& info)
{
 Local self = info.Holder();
 Local wrap = Local::Cast(self->GetInternalField(0));
 void* ptr = wrap->Value();

 Local context(info.GetIsolate()->GetCurrentContext());
 static_cast(ptr)->setAge(value->ToUint32(context).ToLocalChecked()->Value());
}

4) 建立C++类(Person)的ObjectTemplate

void createPersonObjectTemplate(Isolate* isolate, Local global)

{

  HandleScope handle_scope(isolate);

  // JS脚本中C++类的名称(new XXX)

  Local scClassName = String::NewFromUtf8(isolate, "Person", NewStringType::kInternalized).ToLocalChecked();

  // 类Person的模板,关联构造函数

  Local cPersonTpl = FunctionTemplate::New(isolate, newPerson);

  // 设置类名称

  cPersonTpl->SetClassName(scClassName);

  // 为JS脚本对象设置内部域的个数(这个知道怎么用,但是不是很清楚为什么),在这儿用来保存本地实例指针(在构造函数中new的实例)

  cPersonTpl->InstanceTemplate()->SetInternalFieldCount(1);

 

  ///////////////////////////////////////////////////////////////////

  // 设置C++类在JS脚本中的属性模板,并不是说C++中的所有属性都共享给JS。在这儿是将(2-3)类可使用属性和类模板的属性模板关联起来

  // 获取类模板的属性模板

  Local person_proto = cPersonTpl->PrototypeTemplate();

  // 设置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 global = ObjectTemplate::New(GetIsolate());

 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 = Context::New(GetIsolate(), NULL, global);
 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();

阅读(2504) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~