#ifndef JS_BINDER_V8__H__ #define JS_BINDER_V8__H__ #include #include #include "JSCProxyType.h" #include #include #include "JSCProxyTrnasfer.h" #include using namespace v8; namespace laya { //js的析构,这个是非全局对象的。直接删除创建的c对象 template static void JsDestructor(const WeakCallbackInfo >& data) { Isolate* pIso = data.GetIsolate(); //Isolate* pIso1 = Isolate::GetCurrent(); HandleScope __lHandleScope(pIso); Persistent *pPersistentVal = data.GetParameter(); pPersistentVal->Reset(); T *ptr = (T *)data.GetInternalField(0); delete ptr; delete pPersistentVal; //TODO } //这个是绑定全局对象的。不能直接删除c对象 template static void JsDestructor1(const WeakCallbackInfo >& data) { Isolate* pIso = data.GetIsolate();// Isolate::GetCurrent(); HandleScope __lHandleScope(pIso); Persistent *pPersistentVal = data.GetParameter(); T *ptr = (T *)data.GetInternalField(0); //delete ptr; pPersistentVal->Reset(); delete pPersistentVal; } //直接根据c的类创建一个对应的js对象。 并绑定一个已经存在的c对象 //如果weak=true则表示由js负责这个对象的删除(通过weakCallback)。 template Local createJsObjAttachCObj(T* cobj, bool weak) { Isolate* pIso = Isolate::GetCurrent(); EscapableHandleScope handle_scope(pIso); Persistent* pTemp = (Persistent*)T::JSCLSINFO.objTemplate; if (!pTemp) { return Local::Cast(Null(pIso)); } Handle pTempl = Local::New(pIso, pTemp->Get(pIso)); Handle pNewIns = pTempl->NewInstance();// pNewIns->SetAlignedPointerInInternalField(0, cobj); pNewIns->SetAlignedPointerInInternalField(1, (void*)&T::JSCLSINFO); Persistent* pPersist = new Persistent(pIso, pNewIns); cobj->mpJsIso = pIso; cobj->mpJsThis = pPersist; if (weak) { pPersist->SetWeak(pPersist, JsDestructor, v8::WeakCallbackType::kInternalFields); } cobj->createRefArray(); return handle_scope.Escape(pNewIns); } typedef Local JsValue; typedef Local JsString; typedef FunctionCallbackInfo JsFuncArgs; typedef Local JsFunction; inline JsString Js_Str(Isolate* pIso, const char* str) { return String::NewFromUtf8(pIso, str); } //下面这个主要是处理void的,让void能像普通返回值 一样,避免下面还要区分是否是void template struct imp_ToJSValue { static JsValue trans(T t) { return __TransferToJs::ToJs(t); } }; template JsValue ToJSValue(T t) { return imp_ToJSValue::trans(t); } template<> struct imp_ToJSValue { static JsValue trans(void) { return Null(Isolate::GetCurrent()); } }; //template<> //struct imp_ToJSValue { // static JsValue trans(void* t) { // Value* pv = (Value*)t; // if (pv->IsString()) { // return pv->ToString(); // } // else if (pv->IsInt32()) { // return pv->ToInt32(); // } // else // return pv->ToObject(); // return Null(Isolate::GetCurrent()); // } //}; template<> struct imp_ToJSValue { static JsValue trans(JsValue t) { return t; } }; template<> struct imp_ToJSValue { static JsValue trans(int t) { return Integer::New(Isolate::GetCurrent(), t); } }; ////这种情况下直接返回的就是js对象,是Value,Object之类的,不是Local<> //template<> //struct imp_ToJSValue { // static JsValue trans(const void* v) { // Value* pv = (Value*)v; // if (pv->IsString()) { // return pv->ToString(); // } // else if (pv->IsInt32()) { // return pv->ToInt32(); // } // else if (pv->IsObject()) // return pv->ToObject(); // else if (pv->IsBoolean()) // return pv->ToBoolean(); // else if (pv->IsUint32()) // return pv->ToUint32(); // else if (pv->IsNumber()) // return pv->ToNumber(); // //不能各种类型都遍历,由于基本类型一般不会返回void* // //其他类型都是从Object继承的,所以这里简化处理一下。 // return Null(Isolate::GetCurrent()); // } //}; /* template<> struct ToJSValue { static JsValue trans(int64_t t) { return Local::New(Isolate::GetCurrent(),t); } }; */ void imp_js2cfunc_common(const FunctionCallbackInfo& args); //函数无法偏特化,所以用类封装一下 template struct imp_JS2CFunc { static void call(const FunctionCallbackInfo& args) { //偏特化去实现。 imp_js2cfunc_common(args); } }; //直接根据c的类创建一个对应的js对象。 retObj是返回的c对象 //需要能调到上面的构造函数 template Local createAJsObj(T*& retobj) { Isolate* pIso = Isolate::GetCurrent(); EscapableHandleScope handle_scope(pIso); Persistent* pTemp = (Persistent*)T::JSCLSINFO.objTemplate; if (!pTemp) { retobj = NULL; return Local::Cast(Null(pIso)); } Handle pTempl = Local::New(pIso, pTemp->Get(pIso)); Handle pNewIns = pTempl->NewInstance(); //不知道为什么他不会调用上面的构造,所以自己来做 //retobj = (T*)Local::Cast(pNewIns->GetInternalField(0))->Value(); T* obj = new T; obj->mpJsIso = pIso; pNewIns->SetAlignedPointerInInternalField(0, obj); pNewIns->SetAlignedPointerInInternalField(1, (void*)&T::JSCLSINFO); Persistent* pPersist = new Persistent(pIso, pNewIns); obj->mpJsThis = pPersist; pPersist->SetWeak(obj->mpJsThis, JsDestructor, v8::WeakCallbackType::kInternalFields); obj->createRefArray(); //obj->JSConstructor((JsFuncArgs&)args); retobj = obj; return handle_scope.Escape(pNewIns); } //保存函数指针,是为了给js回调用。 template struct FuncInfo { T func; FuncInfo(T f) { func = f; } }; //封装两个函数的对象。例如可以保存get,set函数 template struct FuncInfo2 { F1 f1; F2 f2; FuncInfo2(F1 a, F2 b) { f1 = a; f2 = b; } }; //保存属性的get和set函数,只能是类函数,提供类名和数据类型 template struct PropFuncInfo { G fGet; S fSet; PropFuncInfo(G g, S s) { fGet = g; fSet = s; } PropFuncInfo(G g) {//只读的构造 fGet = g; fSet = 0; //这个不知道怎么赋值,没法阻止错误使用 } }; //属性相关///////////////////////////////// //只能是对象的函数 template struct imp_JsGetProp { static void call(Local property, const PropertyCallbackInfo& info) { assert(false); } }; template struct imp_JsGetProp { static void call(Local property, const PropertyCallbackInfo& info) { PropFuncInfo< R(Cls::*)(void), S>* funcInfo = (PropFuncInfo< R(Cls::*)(void), S>*)External::Cast(*info.Data())->Value(); Local pthis = info.This(); JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1); if (!IsSubClass(id)) { LOGE("throw !IsSubClass %d", id->ClsID); throw - 1; } //if (id != Cls::JSCLSINFO.ClsID) throw - 1; Cls *pObj = (Cls*)pthis->GetAlignedPointerFromInternalField(0); info.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->fGet)())); } }; template struct imp_JsSetProp { static void call(Local property, Local value, const PropertyCallbackInfo& info) { assert(false); } }; template struct imp_JsSetProp { static void call(Local property, Local value, const PropertyCallbackInfo& info) { PropFuncInfo* funcInfo = (PropFuncInfo*)External::Cast(*info.Data())->Value(); Local pthis = info.This(); JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1); if (!IsSubClass(id)) { LOGE("throw !IsSubClass2 %d", id->ClsID); throw - 1; } //if (id != Cls::JSCLSINFO.ClsID) throw - 1; Cls *pObj = (Cls*)pthis->GetAlignedPointerFromInternalField(0); (pObj->*funcInfo->fSet)(__TransferToCpp::ToCpp(value)); } }; //Set还带返回值的情况 template struct imp_JsSetProp { static void call(Local property, Local value, const PropertyCallbackInfo& info) { PropFuncInfo* funcInfo = (PropFuncInfo*)External::Cast(*info.Data())->Value(); Local pthis = info.This(); JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1); if (!IsSubClass(id)) { LOGE("throw !IsSubClass3 %d", id->ClsID); throw - 1; } //if (id != Cls::JSCLSINFO.ClsID) throw - 1; Cls *pObj = (Cls*)pthis->GetAlignedPointerFromInternalField(0); T ret = (pObj->*funcInfo->fSet)(__TransferToCpp::ToCpp(value)); info.GetReturnValue().Set(ToJSValue(ret)); } }; /////////////////////////////////////////// //要求cfunc必须是类成员函数,因为调用的时候是那么假设的 //让一个js的FunctionTemplate调用到指定的c函数 //template //Local bindV8(Local func, T cfunc) { // Isolate* pIso = Isolate::GetCurrent(); // //函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void* // Handle data = External::New(pIso, (void*)*(int*)&cfunc); // func->SetCallHandler(imp_bindv8cCB::call, data); // //return imp_bindv8c::call(func, cfunc, ptr); // return func->GetFunction(); //} template Local WrapCFuncAsInt(T cfunc) { Isolate* pIso = Isolate::GetCurrent(); //函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void* return External::New(pIso, (void*)*(int*)&cfunc); } //由於v8在js對象的0的位置存了c對象了,所以只要傳函數地址就行了 template Local createJSMethod(T cfunc) { Isolate* pIso = Isolate::GetCurrent(); Local method = FunctionTemplate::New(pIso); FuncInfo* pData = new FuncInfo(cfunc); //怎么释放呢 //函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void* Handle data = External::New(pIso, pData);// (void*)*(int*)&cfunc); method->SetCallHandler(imp_JS2CFunc::call, data); return method->GetFunction(); } template void addJSMethod(const char* name, v8::Local that, T cfunc) { Isolate* pIso = Isolate::GetCurrent(); FuncInfo* pData = new FuncInfo(cfunc); //怎么释放呢 //函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void* Handle data = External::New(pIso, pData);// (void*)*(int*)&cfunc); //instancTemp->SetNativeDataProperty(Js_Str(pIso, name), imp_JS2CFunc::call, 0, data); v8::Local signature = v8::Signature::New(pIso, that); v8::Local t = v8::FunctionTemplate::New(pIso, imp_JS2CFunc::call, data, signature); // kInternalized strings are created in the old space. const v8::NewStringType type = v8::NewStringType::kInternalized; v8::Local name_string = v8::String::NewFromUtf8(pIso, name, type).ToLocalChecked(); that->PrototypeTemplate()->Set(name_string, t); t->SetClassName(name_string); // NODE_SET_PROTOTYPE_METHOD() compatibility. } //直接封装符合v8标准的指定函数 Local createJSMethodRaw(FunctionCallback func, JsValue data); /////////js对象的基类//////////////// class JSObjBaseV8 { friend class JsObjHandle2; public: JSObjBaseV8(); virtual ~JSObjBaseV8(); void retainThis(); //防止自己被刪除,例如做異步任務的時候。 void releaseThis(); //可以被刪除了。 static void destroyWeakCB(const WeakCallbackInfo >& data); static void destroyWeakRefArray(const WeakCallbackInfo >& data); //自己创建一个js对象,主要用于不是与某个固定js对象关联的,又需要 //持久引用的临时对象,这时候的this就不是弱引用了,需要主动删掉 void createJSObj(); //void addRefHandle(JsObjHandle2* handle); //創建一個數組,用於保存引用的js對象。 void createRefArray(); void setRefObj(int idx, JsValue obj); Local getRefObj(int idx); //检查js环境是否变化了,一般用来异步回调的保护 bool IsMyJsEnv() { return Isolate::GetCurrent() == mpJsIso; } void setJSArgs(const JsFuncArgs* args) { mpCurJsArgs = args; }; Persistent* weakHoldJsObj(Local& pobj); //通过jsthis来调用函数 inline JsValue _callJsFunc(JsFunction& func, int argc, JsValue argv[]) { EscapableHandleScope sc(mpJsIso); //TODO 能不能不用再new local了 //Local localfunc = Local::New(mpJsIso, Persistent::Cast(func)); Local localthis = Local::New(mpJsIso, Persistent::Cast(*mpJsThis)); //int argc = 0; //v8::Local argv[1]; return sc.Escape(func->Call(localthis, argc, argv)); } JsValue callJsFunc(JsFunction& func); template JsValue callJsFunc(JsFunction& func, P1 p1) { int argc = 1; Local argv[1]; argv[0] = __TransferToJs::ToJs(p1); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2) { int argc = 2; Local argv[2]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3) { int argc = 3; Local argv[3]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4) { int argc = 4; Local argv[4]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { int argc = 5; Local argv[5]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { int argc = 6; Local argv[6]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { int argc = 7; Local argv[7]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); argv[6] = __TransferToJs::ToJs(p7); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { int argc = 8; Local argv[8]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); argv[6] = __TransferToJs::ToJs(p7); argv[7] = __TransferToJs::ToJs(p8); return _callJsFunc(func, argc, argv); } template JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) { int argc = 12; Local argv[12]; argv[0] = __TransferToJs::ToJs(p1); argv[1] = __TransferToJs::ToJs(p2); argv[2] = __TransferToJs::ToJs(p3); argv[3] = __TransferToJs::ToJs(p4); argv[4] = __TransferToJs::ToJs(p5); argv[5] = __TransferToJs::ToJs(p6); argv[6] = __TransferToJs::ToJs(p7); argv[7] = __TransferToJs::ToJs(p8); argv[8] = __TransferToJs::ToJs(p9); argv[9] = __TransferToJs::ToJs(p10); argv[10] = __TransferToJs::ToJs(p11); argv[11] = __TransferToJs::ToJs(p12); return _callJsFunc(func, argc, argv); } public: //js调用当前函数的时候的参数。主要是有时候想要获得一些具体的变量, //所有的公用这一个,所以是非线程安全的 const JsFuncArgs* mpCurJsArgs; Persistent* mpJsThis; //value太基础了,用object,反正function也是object Persistent* mpRefArray; Isolate* mpJsIso; protected: Persistent mRetainedThis; bool mbWeakThis; unsigned short mnRefArrSize; }; class MyJsObjHandle { public: }; struct JsValue2Handle { int id; JSObjBaseV8* pobj; JsValue v; }; class JsObjHandle2 :public MyJsObjHandle { public: JsObjHandle2() { m_pObj = NULL; m_nID = 0; } JSObjBaseV8* m_pObj; int m_nID; //數組下標 Local m_pReturn; bool Empty(); JsValue getJsObj() { if (!m_pObj) return Undefined(Isolate::GetCurrent()); return m_pObj->getRefObj(m_nID); } //引用另外一個js對象, 只拷貝內容,idx不要拷。 JsObjHandle2 &operator=(JsObjHandle2 *p_Val) { if (m_pObj) m_pObj->setRefObj(m_nID, p_Val->getJsObj()); return *this; } //不允许直接从JsValue赋值 //JsObjHandle2 &operator=(JsValue v) JsObjHandle2 &operator=(JsValue2Handle& v) { if (m_pObj) { m_pObj = v.pobj; m_nID = v.id; m_pObj->setRefObj(m_nID, v.v); } return *this; } void set(int id, JSObjBaseV8* pobj, JsValue& v) { m_pObj = pobj; m_nID = id; if (m_pObj) m_pObj->setRefObj(m_nID, v); } void set(JsValue& v); template static bool IsTypeof(JsValue& val) { if (val.IsEmpty()) return false; __InferType<_Tp> _it; switch (_it.iType) { case __VT_void: return false; case __VT_string: return val->IsString(); case __VT_bool: return val->IsBoolean(); case __VT_int: case __VT_long: return (val->IsInt32() || val->IsUint32()); case __VT_float: case __VT_double: case __VT_longlong: return val->IsNumber(); case __VT_ArrayBuffer: return val->IsArrayBuffer(); default: { if (!val->IsObject()) return false; int clsid = *(int*)val.As()->GetAlignedPointerFromInternalField(1); return clsid == (int)&_Tp::JSCLSINFO; } } } template bool IsTypeof() { JsValue val = m_pObj->getRefObj(m_nID); return IsTypeof<_Tp>(val); } template bool Get(_Tp* r) { JsValue v; } //如果类型一致,则能转换,进行转换,否则不转换,返回false。这个主要是针对常用方法进行优化,防止调用两次。 //这个只能处理对象。基本类型用后面的函数 template static bool tryGet(JsValue& val, _R **pRet) { Isolate* pIso = Isolate::GetCurrent(); HandleScope handle_scope(pIso); if (val.IsEmpty()) { *pRet = 0; return false; } if (!__TransferToCpp<_R>::is(val)) return false; *pRet = __TransferToCpp<_R*>::ToCpp(val); return true; } static bool tryGetStr(JsValue& val, char** ppRet) { if (val->IsString()) { *ppRet = JsCharToC(val);// __TransferToCpp::ToCpp(val); return true; } return false; } static bool tryGetStrVector(JsValue& val, std::vector& pRet) { if (val->IsArray()) { pRet.clear(); v8::Local pJSArray = v8::Local::Cast(val); int len = pJSArray->Length(); for (int i = 0; i < len; ++i) { v8::Local v = pJSArray->Get(i); const char* _string = JsCharToC(v); pRet.push_back(_string); } return true; } return false; } void Reset() { //这个好多是在js对象析构的时候调用的,这时候,新的v8会非法(js对象已经删了,下面却还要用),所以干脆把这个去掉了,对v8来说 //在js对象析构的时候再做这个本身也没意义。 //缺点是:如果js对象还在的时候要用这个。。。 /* if (m_pObj) { m_pObj->setRefObj(m_nID, Null(m_pObj->mpJsIso)); m_pObj = NULL; } */ } void __BindThis(JsObjHandle2 &p_This) {} bool IsFunction() { return m_pObj->getRefObj(m_nID)->IsFunction(); } bool isValid() { return m_pObj && m_pObj->mpJsIso == Isolate::GetCurrent(); } bool Call() { if (!m_pObj)return false; EscapableHandleScope sc(m_pObj->mpJsIso); JsValue func = m_pObj->getRefObj(m_nID); if (!func->IsFunction()) return false; Local jsfun = Local::Cast(func); m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun)); return true; } template bool Call(P1 p1) { if (!m_pObj)return false; EscapableHandleScope sc(m_pObj->mpJsIso); JsValue func = m_pObj->getRefObj(m_nID); if (!func->IsFunction()) return false; Local jsfun = Local::Cast(func); m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1)); return true; } #define CALLJSPRE \ if (!m_pObj)return false;\ EscapableHandleScope sc(m_pObj->mpJsIso);\ JsValue func = m_pObj->getRefObj(m_nID);\ if (!func->IsFunction())\ return false;\ Local jsfun = Local::Cast(func); template bool Call(P1 p1, P2 p2) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2)); return true; } template bool Call(P1 p1, P2 p2, P3 p3) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3)); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3, p4)); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3, p4, p5)); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3, p4, p5, p6)); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3, p4, p5, p6, p7)); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3, p4, p5, p6, p7, p8)); return true; } template bool Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) { CALLJSPRE m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3, p4, p5, p6, p7, p8, p9)); return true; } }; //typedef JSObjBaseV8 JsObjHandle; //为了与原来的差不多的宏。 只能在对象的实例中使用。必须按照下面的顺序调用。 //第一个name是类名,统计用的 #define JSP_CLASS(name,cls) \ v8::Isolate* pJsIso = v8::Isolate::GetCurrent(); \ v8::HandleScope sc(pJsIso); \ v8::Local xhrtemp = v8::FunctionTemplate::New(pJsIso, JSCClass::JsConstructor); \ xhrtemp->SetClassName(Js_Str(pJsIso, name)); \ v8::Local instancTemp = xhrtemp->InstanceTemplate(); \ instancTemp->SetInternalFieldCount(2); \ cls::JSCLSINFO.objTemplate = new Persistent(pJsIso, instancTemp); \ v8::Local pCtx = pJsIso->GetCurrentContext(); //这个的区别是不能直接创建c对象,而是绑定一个已经存在的对象。 #define JSP_GLOBAL_CLASS(name,cls) \ v8::Isolate* pJsIso = Isolate::GetCurrent(); /*全局的每次都重新创建*/\ v8::HandleScope sc(pJsIso); \ v8::Local xhrtemp = v8::FunctionTemplate::New(pJsIso); \ xhrtemp->SetClassName(Js_Str(pJsIso, name)); \ v8::Local instancTemp = xhrtemp->InstanceTemplate(); \ instancTemp->SetInternalFieldCount(2); \ cls::JSCLSINFO.objTemplate = new Persistent(pJsIso, instancTemp); \ v8::Local pCtx = pJsIso->GetCurrentContext(); #define JSP_REG_CONSTRUCTOR(cls,...) \ JSCClass::getInstance()->addConstructor(regConstructor()); #define JSP_ADD_FIXED_PROPERTY(name,cls,val) \ instancTemp->Set(Js_Str(pJsIso, #name), __TransferToJs::ToJs(val)); #define JSP_ADD_METHOD(name,fn) \ addJSMethod(name,xhrtemp, &fn); #define JSP_ADD_METHODRAW(name, func, data) \ instancTemp->Set(Js_Str(pJsIso, name), createJSMethodRaw(func,data)); #define JSP_INSTALL_CLASS(name,cls) \ pCtx->Global()->Set(Js_Str(pJsIso, name), xhrtemp->GetFunction()); \ JSClassMgr::GetThreadInstance()->allCls.push_back(JSCClass::reset); #define JSP_INSTALL_G_CLASS(name,cls,inst) \ Local jsinst = instancTemp->NewInstance();\ jsinst->SetAlignedPointerInInternalField(0, inst); \ jsinst->SetAlignedPointerInInternalField(1, &cls::JSCLSINFO); \ Persistent* pPersist = new Persistent(pJsIso, jsinst);\ inst->mpJsThis = pPersist;\ pPersist->SetWeak(pPersist, JsDestructor1, v8::WeakCallbackType::kInternalFields);\ createRefArray();\ pCtx->Global()->Set(Js_Str(pJsIso, name), jsinst); //注意,下面的inst是返回的。 #define JSP_INSTALL_GLOBAL_CLASS(name,cls,inst) \ pCtx->Global()->Set(Js_Str(pJsIso, name), createJsObjAttachCObj(inst,false)); //添加一个只读属性。get是函数地址,funcplace是一个存放get和set函数地址的结构的指针 #define JSP_ADD_PROPERTY_RO(name,cls,get) \ static PropFuncInfo propFunc_R##cls##name(&cls::get); \ instancTemp->SetAccessor(Js_Str(pJsIso,#name), \ imp_JsGetProp::call,0, \ External::New(pJsIso, (void*)&propFunc_R##cls##name),v8::DEFAULT, v8::ReadOnly); #define JSP_ADD_PROPERTY(name,cls,get,set) \ static PropFuncInfo propFunc_##cls##name(&cls::get, &cls::set); \ instancTemp->SetAccessor(Js_Str(pJsIso,#name), \ imp_JsGetProp::call,imp_JsSetProp::call, \ External::New(pJsIso, (void*)&propFunc_##cls##name)); #define JSP_GLOBAL_START1() \ v8::Isolate* pIso = v8::Isolate::GetCurrent(); \ v8::HandleScope sc(pIso); \ v8::Local pCtx = pIso->GetCurrentContext(); \ v8::Local gctx = pCtx->Global(); //func必须是全局函数,不允许成员函数。为了简单,还是与原来的兼容把 #define JSP_ADD_GLOBAL_FUNCTION(name, func, ...) \ gctx->Set(Js_Str(pIso, #name), createJSMethod(func)); #define JSP_ADD_GLOBAL_PROPERTY(name, v) \ gctx->Set(Js_Str(pIso, #name), ToJSValue(v)); //检查参数是否>=num个 bool checkJSToCArgs(const FunctionCallbackInfo& args, int num); ///////////////////////////////////////////////////////// //回调的偏特化 //没有参数 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(void); static void call(const FunctionCallbackInfo& args) { void* pExData = External::Cast(*args.Data())->Value(); //FuncInfo* funcInfo = (FuncInfo*)(&pExData); FuncInfo* funcInfo = (FuncInfo*)pExData; Local pthis = args.This(); JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1); if (!IsSubClass(id)) { LOGE("throw !IsSubClass 878 %d", id->ClsID); throw - 1; } //if (id != Cls::JSCLSINFO.ClsID) throw - 1; Cls *pObj = (Cls*)pthis->GetAlignedPointerFromInternalField(0); pObj->setJSArgs(&args); args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)())); } }; #define JS2CCALL_INIT \ void* pExData = External::Cast(*args.Data())->Value();\ FuncInfo* funcInfo = (FuncInfo*)pExData;\ Local pthis = args.This(); #define JS2CCALL_GET_COBJ \ JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1);\ if (!IsSubClass(id)){LOGE("throw isSubClass %d",id->ClsID); throw - 1;}\ Cls *pObj = (Cls*)pthis->GetAlignedPointerFromInternalField(0);\ pObj->setJSArgs(&args); #define JS2CCALL_GET_PARAMS1 \ if(!checkJSToCArgs(args,1))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]); #define JS2CCALL_GET_PARAMS2 \ if(!checkJSToCArgs(args,2))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]); #define JS2CCALL_GET_PARAMS3 \ if(!checkJSToCArgs(args,3))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]); #define JS2CCALL_GET_PARAMS4 \ if(!checkJSToCArgs(args,4))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]); #define JS2CCALL_GET_PARAMS5 \ if(!checkJSToCArgs(args,5))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]); #define JS2CCALL_GET_PARAMS6 \ if(!checkJSToCArgs(args,6))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]); #define JS2CCALL_GET_PARAMS7 \ if(!checkJSToCArgs(args,7))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]);\ P7 p7 = __TransferToCpp::ToCpp(args[6]); #define JS2CCALL_GET_PARAMS8 \ if(!checkJSToCArgs(args,8))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]);\ P7 p7 = __TransferToCpp::ToCpp(args[6]);\ P8 p8 = __TransferToCpp::ToCpp(args[7]); #define JS2CCALL_GET_PARAMS9 \ if(!checkJSToCArgs(args,9))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]);\ P7 p7 = __TransferToCpp::ToCpp(args[6]);\ P8 p8 = __TransferToCpp::ToCpp(args[7]);\ P9 p9 = __TransferToCpp::ToCpp(args[8]); #define JS2CCALL_GET_PARAMS10 \ if(!checkJSToCArgs(args,10))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]);\ P7 p7 = __TransferToCpp::ToCpp(args[6]);\ P8 p8 = __TransferToCpp::ToCpp(args[7]);\ P9 p9 = __TransferToCpp::ToCpp(args[8]);\ P10 p10 = __TransferToCpp::ToCpp(args[9]); #define JS2CCALL_GET_PARAMS11 \ if(!checkJSToCArgs(args,11))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]);\ P7 p7 = __TransferToCpp::ToCpp(args[6]);\ P8 p8 = __TransferToCpp::ToCpp(args[7]);\ P9 p9 = __TransferToCpp::ToCpp(args[8]);\ P10 p10 = __TransferToCpp::ToCpp(args[9]);\ P11 p11 = __TransferToCpp::ToCpp(args[10]); #define JS2CCALL_GET_PARAMS12 \ if(!checkJSToCArgs(args,12))return;\ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]);\ P4 p4 = __TransferToCpp::ToCpp(args[3]);\ P5 p5 = __TransferToCpp::ToCpp(args[4]);\ P6 p6 = __TransferToCpp::ToCpp(args[5]);\ P7 p7 = __TransferToCpp::ToCpp(args[6]);\ P8 p8 = __TransferToCpp::ToCpp(args[7]);\ P9 p9 = __TransferToCpp::ToCpp(args[8]);\ P10 p10 = __TransferToCpp::ToCpp(args[9]);\ P11 p11 = __TransferToCpp::ToCpp(args[10]);\ P12 p12 = __TransferToCpp::ToCpp(args[11]); //一个参数 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS1; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1))); resetJsStrBuf(); } }; //2 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS2; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2))); resetJsStrBuf(); } }; //3 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS3; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3))); resetJsStrBuf(); } }; //4 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS4; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4))); resetJsStrBuf(); } }; //5 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4, P5); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS5; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4, p5))); resetJsStrBuf(); } }; //6 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS6; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6))); resetJsStrBuf(); } }; //7 template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS7; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7))); resetJsStrBuf(); } }; template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS8; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8))); resetJsStrBuf(); } }; template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS9; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9))); resetJsStrBuf(); } }; template struct imp_JS2CFunc { typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS12; args.GetReturnValue().Set(ToJSValue((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12))); resetJsStrBuf(); } }; //下面是void的,没想到好办法 //没有参数 template struct imp_JS2CFunc { typedef void(Cls::*funcType)(void); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; (pObj->*funcInfo->func)(); } }; //一个参数 template< typename Cls, typename P1 > struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS1; (pObj->*(funcInfo->func))(p1); resetJsStrBuf(); } }; //2 template struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS2; (pObj->*funcInfo->func)(p1, p2); resetJsStrBuf(); } }; //3 template struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS3; (pObj->*funcInfo->func)(p1, p2, p3); resetJsStrBuf(); } }; //4 template< typename Cls, typename P1, typename P2, typename P3, typename P4 > struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS4; (pObj->*funcInfo->func)(p1, p2, p3, p4); resetJsStrBuf(); } }; //5 template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5 > struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS5; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5); resetJsStrBuf(); } }; //6 template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6 > struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS6; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6); resetJsStrBuf(); } }; //7 template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 > struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS7; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7); resetJsStrBuf(); } }; //9 template struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS9; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9); resetJsStrBuf(); } }; template struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS10; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); resetJsStrBuf(); } }; //11 template< typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11 > struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS11; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); resetJsStrBuf(); } }; template struct imp_JS2CFunc { typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_COBJ; JS2CCALL_GET_PARAMS12; (pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); resetJsStrBuf(); } }; //非类函数 template<> //void(void) struct imp_JS2CFunc { typedef void(*funcType)(void); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; funcInfo->func(); } }; template//R(void) struct imp_JS2CFunc { typedef R(*funcType)(void); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; args.GetReturnValue().Set(ToJSValue(funcInfo->func())); } }; template//R(p1) struct imp_JS2CFunc { typedef R(*funcType)(P1); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS1; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1))); resetJsStrBuf(); } }; template//const R(p1) struct imp_JS2CFunc { typedef const R(*funcType)(P1); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS1; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1))); resetJsStrBuf(); } }; template struct imp_JS2CFunc {//void(p1) typedef void(*funcType)(P1); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS1; funcInfo->func(p1); resetJsStrBuf(); } }; template//R(p1,p2) struct imp_JS2CFunc { typedef R(*funcType)(P1, P2); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS2; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2))); resetJsStrBuf(); } }; template//void(p1,p2) struct imp_JS2CFunc { typedef void(*funcType)(P1, P2); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS2; funcInfo->func(p1, p2); resetJsStrBuf(); } }; template//3 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS3; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3))); resetJsStrBuf(); } }; template//4 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3, P4); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS4; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3, p4))); resetJsStrBuf(); } }; template//5 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3, P4, P5); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS5; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3, p4, p5))); resetJsStrBuf(); } }; template//6 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3, P4, P5, P6); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS6; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3, p4, p5, p6))); resetJsStrBuf(); } }; template//7 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3, P4, P5, P6, P7); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS7; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3, p4, p5, p6, p7))); resetJsStrBuf(); } }; template//8 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS8; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8))); resetJsStrBuf(); } }; template//9 struct imp_JS2CFunc { typedef R(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS9; args.GetReturnValue().Set(ToJSValue(funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8, p9))); resetJsStrBuf(); } }; //void template< typename P1, typename P2, typename P3>//3 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS3; funcInfo->func(p1, p2, p3); resetJsStrBuf(); } }; template//4 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS4; funcInfo->func(p1, p2, p3, p4); resetJsStrBuf(); } }; template//5 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4, P5); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS5; funcInfo->func(p1, p2, p3, p4, p5); resetJsStrBuf(); } }; template//6 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4, P5, P6); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS6; funcInfo->func(p1, p2, p3, p4, p5, p6); resetJsStrBuf(); } }; template< typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>//7 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS7; funcInfo->func(p1, p2, p3, p4, p5, p6, p7); resetJsStrBuf(); } }; template//8 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS8; funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8); resetJsStrBuf(); } }; template//9 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS9; funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8, p9); resetJsStrBuf(); } }; template//12 struct imp_JS2CFunc { typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12); static void call(const FunctionCallbackInfo& args) { JS2CCALL_INIT; JS2CCALL_GET_PARAMS12; funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); resetJsStrBuf(); } }; //构造函数相关 struct IJSCCallback { virtual ~IJSCCallback() {} virtual void* constructor(const FunctionCallbackInfo& args) { throw "not implemented"; } virtual uint16_t getNumArgs() = 0; }; #define JS2CCONSTRUCTOR_GET_PARAMS1 \ P1 p1 = __TransferToCpp::ToCpp(args[0]); #define JS2CCONSTRUCTOR_GET_PARAMS2 \ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]); #define JS2CCONSTRUCTOR_GET_PARAMS3 \ P1 p1 = __TransferToCpp::ToCpp(args[0]);\ P2 p2 = __TransferToCpp::ToCpp(args[1]);\ P3 p3 = __TransferToCpp::ToCpp(args[2]); template struct JSCConstructor0 : public IJSCCallback { virtual void* constructor(const FunctionCallbackInfo& args) { return new Cls(); } virtual uint16_t getNumArgs() { return 0; } }; template IJSCCallback* regConstructor() { return new JSCConstructor0(); } template struct JSCConstructor1 :public IJSCCallback { virtual void* constructor(const FunctionCallbackInfo& args) { JS2CCONSTRUCTOR_GET_PARAMS1; return new Cls(p1); } virtual uint16_t getNumArgs() { return 1; } }; template IJSCCallback* regConstructor() { return new JSCConstructor1(); } template struct JSCConstructor2 :public IJSCCallback { virtual void* constructor(const FunctionCallbackInfo& args) { JS2CCONSTRUCTOR_GET_PARAMS2; return new Cls(p1, p2); } virtual uint16_t getNumArgs() { return 2; } }; template struct JSCConstructor3 :public IJSCCallback { virtual void* constructor(const FunctionCallbackInfo& args) { JS2CCONSTRUCTOR_GET_PARAMS3; return new Cls(p1, p2, p3); } virtual uint16_t getNumArgs() { return 3; } }; template IJSCCallback* regConstructor() { return new JSCConstructor2(); } template IJSCCallback* regConstructor() { return new JSCConstructor3(); } template class JSCClass { public: class FuncEntry { enum { Max_Arg_Size = 12, Invalid_size = -1, }; IJSCCallback *m_funcs[Max_Arg_Size + 1]; int m_iMaxArgSize; public: FuncEntry() { m_iMaxArgSize = Invalid_size; memset(m_funcs, 0, sizeof(m_funcs)); } ~FuncEntry() { reset(); } void reset() { for (int i = 0; i <= Max_Arg_Size; ++i) { if (0 != m_funcs[i]) { delete m_funcs[i]; m_funcs[i] = 0; } } } void add(IJSCCallback *p_fn) { assert(p_fn != nullptr && p_fn->getNumArgs() <= Max_Arg_Size && m_funcs[p_fn->getNumArgs()] == nullptr); if (m_iMaxArgSize < p_fn->getNumArgs()) m_iMaxArgSize = p_fn->getNumArgs(); m_funcs[p_fn->getNumArgs()] = p_fn; } IJSCCallback *get(int p_iArgNum) { if (Invalid_size == m_iMaxArgSize) { return 0; } if (p_iArgNum > m_iMaxArgSize) p_iArgNum = m_iMaxArgSize; for (; p_iArgNum >= 0; p_iArgNum--) { if (0 != m_funcs[p_iArgNum]) return m_funcs[p_iArgNum]; } return 0; } }; JSCClass() { } ~JSCClass() { _reset(); } static JSCClass* getInstance() { static JSCClass instance; return &instance; } void addConstructor(IJSCCallback* constructor) { m_Constructor.add(constructor); } static void reset() { JSCClass::getInstance()->_reset(); } static void JsConstructor(const FunctionCallbackInfo& args) { if (!args.IsConstructCall()) { printf("not a Construct Call)\n"); return; } IJSCCallback *pfn = JSCClass::getInstance()->m_Constructor.get(args.Length()); Isolate* pIso = Isolate::GetCurrent(); HandleScope handle_scope(pIso); Local pthis = args.This(); T* obj = nullptr; if (0 == pfn) { obj = new T; } else { obj = (T*)pfn->constructor(args); } obj->mpJsIso = pIso; pthis->SetAlignedPointerInInternalField(0, obj); pthis->SetAlignedPointerInInternalField(1, (void*)&T::JSCLSINFO); Persistent* pPersist = new Persistent(pIso, pthis); obj->mpJsThis = pPersist; pPersist->SetWeak(pPersist, JsDestructor, v8::WeakCallbackType::kInternalFields); obj->createRefArray(); } private: void _reset() { m_Constructor.reset(); } private: FuncEntry m_Constructor; }; class JSClassMgr { public: typedef void(*RESETFUNC)(); static JSClassMgr* GetThreadInstance() { return &__Ins; } std::vector allCls; void resetAllRegClass() { for (int i = 0, sz = allCls.size(); i < sz; i++) { allCls[i](); } allCls.clear(); } private: static thread_local JSClassMgr __Ins; }; } #endif