Files
LayaNative2.0/Conch/source/conch/JSWrapper/JSInterface/V8/JsBinder.h
T
2020-11-11 16:17:13 +08:00

1648 lines
64 KiB
C++

#ifndef JS_BINDER_V8__H__
#define JS_BINDER_V8__H__
#include <v8.h>
#include <type_traits>
#include "JSCProxyType.h"
#include <util/Log.h>
#include <JSObjBase.h>
#include "JSCProxyTrnasfer.h"
#include <cassert>
using namespace v8;
namespace laya {
//js的析构,这个是非全局对象的。直接删除创建的c对象
template <typename T>
static void JsDestructor(const WeakCallbackInfo<Persistent<Object> >& data) {
Isolate* pIso = data.GetIsolate();
//Isolate* pIso1 = Isolate::GetCurrent();
HandleScope __lHandleScope(pIso);
Persistent<Object> *pPersistentVal = data.GetParameter();
pPersistentVal->Reset();
T *ptr = (T *)data.GetInternalField(0);
delete ptr;
delete pPersistentVal; //TODO
}
//这个是绑定全局对象的。不能直接删除c对象
template <typename T>
static void JsDestructor1(const WeakCallbackInfo<Persistent<Object> >& data) {
Isolate* pIso = data.GetIsolate();// Isolate::GetCurrent();
HandleScope __lHandleScope(pIso);
Persistent<Object> *pPersistentVal = data.GetParameter();
T *ptr = (T *)data.GetInternalField(0);
//delete ptr;
pPersistentVal->Reset();
delete pPersistentVal;
}
//直接根据c的类创建一个对应的js对象。 并绑定一个已经存在的c对象
//如果weak=true则表示由js负责这个对象的删除(通过weakCallback)。
template<class T>
Local<Object> createJsObjAttachCObj(T* cobj, bool weak) {
Isolate* pIso = Isolate::GetCurrent();
EscapableHandleScope handle_scope(pIso);
Persistent<ObjectTemplate>* pTemp = (Persistent<ObjectTemplate>*)T::JSCLSINFO.objTemplate;
if (!pTemp) {
return Local<Object>::Cast(Null(pIso));
}
Handle<ObjectTemplate> pTempl = Local<ObjectTemplate>::New(pIso, pTemp->Get(pIso));
Handle<Object> pNewIns = pTempl->NewInstance();//
pNewIns->SetAlignedPointerInInternalField(0, cobj);
pNewIns->SetAlignedPointerInInternalField(1, (void*)&T::JSCLSINFO);
Persistent<Object>* pPersist = new Persistent<Object>(pIso, pNewIns);
cobj->mpJsIso = pIso;
cobj->mpJsThis = pPersist;
if (weak) {
pPersist->SetWeak(pPersist, JsDestructor<T>, v8::WeakCallbackType::kInternalFields);
}
cobj->createRefArray();
return handle_scope.Escape(pNewIns);
}
typedef Local<Value> JsValue;
typedef Local<String> JsString;
typedef FunctionCallbackInfo<Value> JsFuncArgs;
typedef Local<Function> JsFunction;
inline JsString Js_Str(Isolate* pIso, const char* str) {
return String::NewFromUtf8(pIso, str);
}
//下面这个主要是处理void的,让void能像普通返回值 一样,避免下面还要区分是否是void
template <typename T>
struct imp_ToJSValue {
static JsValue trans(T t) {
return __TransferToJs<T>::ToJs(t);
}
};
template<class T>
JsValue ToJSValue(T t) {
return imp_ToJSValue<T>::trans(t);
}
template<>
struct imp_ToJSValue<void> {
static JsValue trans(void) {
return Null(Isolate::GetCurrent());
}
};
//template<>
//struct imp_ToJSValue<void*> {
// 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<JsValue> {
static JsValue trans(JsValue t) {
return t;
}
};
template<>
struct imp_ToJSValue<int> {
static JsValue trans(int t) {
return Integer::New(Isolate::GetCurrent(), t);
}
};
////这种情况下直接返回的就是js对象,是Value,Object之类的,不是Local<>
//template<>
//struct imp_ToJSValue<const void*> {
// 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<int64_t> {
static JsValue trans(int64_t t) {
return Local<Number>::New(Isolate::GetCurrent(),t);
}
};
*/
void imp_js2cfunc_common(const FunctionCallbackInfo<Value>& args);
//函数无法偏特化,所以用类封装一下
template <typename T>
struct imp_JS2CFunc {
static void call(const FunctionCallbackInfo<Value>& args) { //偏特化去实现。
imp_js2cfunc_common(args);
}
};
//直接根据c的类创建一个对应的js对象。 retObj是返回的c对象
//需要能调到上面的构造函数
template<class T>
Local<Object> createAJsObj(T*& retobj) {
Isolate* pIso = Isolate::GetCurrent();
EscapableHandleScope handle_scope(pIso);
Persistent<ObjectTemplate>* pTemp = (Persistent<ObjectTemplate>*)T::JSCLSINFO.objTemplate;
if (!pTemp) {
retobj = NULL;
return Local<Object>::Cast(Null(pIso));
}
Handle<ObjectTemplate> pTempl = Local<ObjectTemplate>::New(pIso, pTemp->Get(pIso));
Handle<Object> pNewIns = pTempl->NewInstance();
//不知道为什么他不会调用上面的构造,所以自己来做
//retobj = (T*)Local<External>::Cast(pNewIns->GetInternalField(0))->Value();
T* obj = new T;
obj->mpJsIso = pIso;
pNewIns->SetAlignedPointerInInternalField(0, obj);
pNewIns->SetAlignedPointerInInternalField(1, (void*)&T::JSCLSINFO);
Persistent<Object>* pPersist = new Persistent<Object>(pIso, pNewIns);
obj->mpJsThis = pPersist;
pPersist->SetWeak(obj->mpJsThis, JsDestructor<T>, v8::WeakCallbackType::kInternalFields);
obj->createRefArray();
//obj->JSConstructor((JsFuncArgs&)args);
retobj = obj;
return handle_scope.Escape(pNewIns);
}
//保存函数指针,是为了给js回调用。
template <typename T>
struct FuncInfo {
T func;
FuncInfo(T f) {
func = f;
}
};
//封装两个函数的对象。例如可以保存get,set函数
template <typename F1, typename F2>
struct FuncInfo2 {
F1 f1;
F2 f2;
FuncInfo2(F1 a, F2 b) {
f1 = a; f2 = b;
}
};
//保存属性的get和set函数,只能是类函数,提供类名和数据类型
template <class G, class S>
struct PropFuncInfo {
G fGet;
S fSet;
PropFuncInfo(G g, S s) {
fGet = g;
fSet = s;
}
PropFuncInfo(G g) {//只读的构造
fGet = g;
fSet = 0; //这个不知道怎么赋值,没法阻止错误使用
}
};
//属性相关/////////////////////////////////
//只能是对象的函数
template <typename G, typename S>
struct imp_JsGetProp {
static void call(Local<String> property, const PropertyCallbackInfo<Value>& info) { assert(false); }
};
template <class Cls, class R, class S>
struct imp_JsGetProp<R(Cls::*)(void), S> {
static void call(Local<String> property, const PropertyCallbackInfo<Value>& info) {
PropFuncInfo< R(Cls::*)(void), S>* funcInfo = (PropFuncInfo< R(Cls::*)(void), S>*)External::Cast(*info.Data())->Value();
Local<Object> pthis = info.This();
JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1);
if (!IsSubClass<Cls>(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<R>((pObj->*funcInfo->fGet)()));
}
};
template <class G, class S>
struct imp_JsSetProp {
static void call(Local<String> property, Local<Value> value, const PropertyCallbackInfo<void>& info) { assert(false); }
};
template <class G, class Cls, class T>
struct imp_JsSetProp<G, void(Cls::*)(T)> {
static void call(Local<String> property, Local<Value> value, const PropertyCallbackInfo<void>& info) {
PropFuncInfo<G, void(Cls::*)(T)>* funcInfo = (PropFuncInfo<G, void(Cls::*)(T) >*)External::Cast(*info.Data())->Value();
Local<Object> pthis = info.This();
JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1);
if (!IsSubClass<Cls>(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<T>::ToCpp(value));
}
};
//Set还带返回值的情况
template <class G, class Cls, class T>
struct imp_JsSetProp<G, T(Cls::*)(T)> {
static void call(Local<String> property, Local<Value> value, const PropertyCallbackInfo<void>& info) {
PropFuncInfo<G, T(Cls::*)(T)>* funcInfo = (PropFuncInfo<G, T(Cls::*)(T)>*)External::Cast(*info.Data())->Value();
Local<Object> pthis = info.This();
JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1);
if (!IsSubClass<Cls>(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<T>::ToCpp(value));
info.GetReturnValue().Set(ToJSValue<T>(ret));
}
};
///////////////////////////////////////////
//要求cfunc必须是类成员函数,因为调用的时候是那么假设的
//让一个js的FunctionTemplate调用到指定的c函数
//template <class T>
//Local<Function> bindV8(Local<FunctionTemplate> func, T cfunc) {
// Isolate* pIso = Isolate::GetCurrent();
// //函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void*
// Handle<Value> data = External::New(pIso, (void*)*(int*)&cfunc);
// func->SetCallHandler(imp_bindv8cCB<T>::call, data);
// //return imp_bindv8c<T>::call(func, cfunc, ptr);
// return func->GetFunction();
//}
template <class T>
Local<Value> WrapCFuncAsInt(T cfunc) {
Isolate* pIso = Isolate::GetCurrent();
//函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void*
return External::New(pIso, (void*)*(int*)&cfunc);
}
//由於v8在js對象的0的位置存了c對象了,所以只要傳函數地址就行了
template <class T>
Local<Function> createJSMethod(T cfunc) {
Isolate* pIso = Isolate::GetCurrent();
Local<FunctionTemplate> method = FunctionTemplate::New(pIso);
FuncInfo<T>* pData = new FuncInfo<T>(cfunc); //怎么释放呢
//函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void*
Handle<Value> data = External::New(pIso, pData);// (void*)*(int*)&cfunc);
method->SetCallHandler(imp_JS2CFunc<T>::call, data);
return method->GetFunction();
}
template <class T>
void addJSMethod(const char* name, v8::Local<v8::FunctionTemplate> that, T cfunc) {
Isolate* pIso = Isolate::GetCurrent();
FuncInfo<T>* pData = new FuncInfo<T>(cfunc); //怎么释放呢
//函數不能轉成數字,只好取地址再轉,但是取的地址是堆栈地址,所以再取*转成int,表示实际地址了,再强转void*
Handle<Value> data = External::New(pIso, pData);// (void*)*(int*)&cfunc);
//instancTemp->SetNativeDataProperty(Js_Str(pIso, name), imp_JS2CFunc<T>::call, 0, data);
v8::Local<v8::Signature> signature = v8::Signature::New(pIso, that);
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(pIso, imp_JS2CFunc<T>::call, data, signature);
// kInternalized strings are created in the old space.
const v8::NewStringType type = v8::NewStringType::kInternalized;
v8::Local<v8::String> 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<Function> createJSMethodRaw(FunctionCallback func, JsValue data);
/////////js对象的基类////////////////
class JSObjBaseV8 {
friend class JsObjHandle2;
public:
JSObjBaseV8();
virtual ~JSObjBaseV8();
void retainThis(); //防止自己被刪除,例如做異步任務的時候。
void releaseThis(); //可以被刪除了。
static void destroyWeakCB(const WeakCallbackInfo<Persistent<Object> >& data);
static void destroyWeakRefArray(const WeakCallbackInfo<Persistent<Array> >& data);
//自己创建一个js对象,主要用于不是与某个固定js对象关联的,又需要
//持久引用的临时对象,这时候的this就不是弱引用了,需要主动删掉
void createJSObj();
//void addRefHandle(JsObjHandle2* handle);
//創建一個數組,用於保存引用的js對象。
void createRefArray();
void setRefObj(int idx, JsValue obj);
Local<Object> getRefObj(int idx);
//检查js环境是否变化了,一般用来异步回调的保护
bool IsMyJsEnv() {
return Isolate::GetCurrent() == mpJsIso;
}
void setJSArgs(const JsFuncArgs* args) { mpCurJsArgs = args; };
Persistent<Object>* weakHoldJsObj(Local<Object>& pobj);
//通过jsthis来调用函数
inline JsValue _callJsFunc(JsFunction& func, int argc, JsValue argv[]) {
EscapableHandleScope sc(mpJsIso);
//TODO 能不能不用再new local了
//Local<Function> localfunc = Local<Function>::New(mpJsIso, Persistent<Function>::Cast(func));
Local<Object> localthis = Local<Object>::New(mpJsIso, Persistent<Object>::Cast(*mpJsThis));
//int argc = 0;
//v8::Local<v8::Value> argv[1];
return sc.Escape(func->Call(localthis, argc, argv));
}
JsValue callJsFunc(JsFunction& func);
template<class P1>
JsValue callJsFunc(JsFunction& func, P1 p1) {
int argc = 1;
Local<Value> argv[1];
argv[0] = __TransferToJs<P1>::ToJs(p1);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2) {
int argc = 2;
Local<Value> argv[2];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3) {
int argc = 3;
Local<Value> argv[3];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3, class P4>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4) {
int argc = 4;
Local<Value> argv[4];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
argv[3] = __TransferToJs<P4>::ToJs(p4);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3, class P4, class P5>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
int argc = 5;
Local<Value> argv[5];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
argv[3] = __TransferToJs<P4>::ToJs(p4);
argv[4] = __TransferToJs<P5>::ToJs(p5);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3, class P4, class P5, class P6>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
int argc = 6;
Local<Value> argv[6];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
argv[3] = __TransferToJs<P4>::ToJs(p4);
argv[4] = __TransferToJs<P5>::ToJs(p5);
argv[5] = __TransferToJs<P6>::ToJs(p6);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
int argc = 7;
Local<Value> argv[7];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
argv[3] = __TransferToJs<P4>::ToJs(p4);
argv[4] = __TransferToJs<P5>::ToJs(p5);
argv[5] = __TransferToJs<P6>::ToJs(p6);
argv[6] = __TransferToJs<P7>::ToJs(p7);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
JsValue callJsFunc(JsFunction& func, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
int argc = 8;
Local<Value> argv[8];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
argv[3] = __TransferToJs<P4>::ToJs(p4);
argv[4] = __TransferToJs<P5>::ToJs(p5);
argv[5] = __TransferToJs<P6>::ToJs(p6);
argv[6] = __TransferToJs<P7>::ToJs(p7);
argv[7] = __TransferToJs<P8>::ToJs(p8);
return _callJsFunc(func, argc, argv);
}
template<class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
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<Value> argv[12];
argv[0] = __TransferToJs<P1>::ToJs(p1);
argv[1] = __TransferToJs<P2>::ToJs(p2);
argv[2] = __TransferToJs<P3>::ToJs(p3);
argv[3] = __TransferToJs<P4>::ToJs(p4);
argv[4] = __TransferToJs<P5>::ToJs(p5);
argv[5] = __TransferToJs<P6>::ToJs(p6);
argv[6] = __TransferToJs<P7>::ToJs(p7);
argv[7] = __TransferToJs<P8>::ToJs(p8);
argv[8] = __TransferToJs<P8>::ToJs(p9);
argv[9] = __TransferToJs<P8>::ToJs(p10);
argv[10] = __TransferToJs<P8>::ToJs(p11);
argv[11] = __TransferToJs<P8>::ToJs(p12);
return _callJsFunc(func, argc, argv);
}
public:
//js调用当前函数的时候的参数。主要是有时候想要获得一些具体的变量,
//所有的公用这一个,所以是非线程安全的
const JsFuncArgs* mpCurJsArgs;
Persistent<Object>* mpJsThis; //value太基础了,用object,反正function也是object
Persistent<Array>* mpRefArray;
Isolate* mpJsIso;
protected:
Persistent<Object> 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<Value> 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 <typename _Tp>
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<Object>()->GetAlignedPointerFromInternalField(1);
return clsid == (int)&_Tp::JSCLSINFO;
}
}
}
template <typename _Tp>
bool IsTypeof() {
JsValue val = m_pObj->getRefObj(m_nID);
return IsTypeof<_Tp>(val);
}
template<typename _Tp>
bool Get(_Tp* r) {
JsValue v;
}
//如果类型一致,则能转换,进行转换,否则不转换,返回false。这个主要是针对常用方法进行优化,防止调用两次。
//这个只能处理对象。基本类型用后面的函数
template <typename _R>
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<char*>::ToCpp(val);
return true;
}
return false;
}
static bool tryGetStrVector(JsValue& val, std::vector<std::string>& pRet) {
if (val->IsArray()) {
pRet.clear();
v8::Local<v8::Array> pJSArray = v8::Local<v8::Array>::Cast(val);
int len = pJSArray->Length();
for (int i = 0; i < len; ++i) {
v8::Local<v8::Value> 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<Function> jsfun = Local<Function>::Cast(func);
m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun));
return true;
}
template <typename P1>
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<Function> jsfun = Local<Function>::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<Function> jsfun = Local<Function>::Cast(func);
template <typename P1, typename P2>
bool Call(P1 p1, P2 p2) {
CALLJSPRE
m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2));
return true;
}
template <typename P1, typename P2, typename P3>
bool Call(P1 p1, P2 p2, P3 p3) {
CALLJSPRE
m_pReturn = sc.Escape(m_pObj->callJsFunc(jsfun, p1, p2, p3));
return true;
}
template <typename P1, typename P2, typename P3, typename P4>
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 <typename P1, typename P2, typename P3, typename P4, typename P5>
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 <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
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 <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
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 <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
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 <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
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<v8::FunctionTemplate> xhrtemp = v8::FunctionTemplate::New(pJsIso, JSCClass<cls>::JsConstructor); \
xhrtemp->SetClassName(Js_Str(pJsIso, name)); \
v8::Local<v8::ObjectTemplate> instancTemp = xhrtemp->InstanceTemplate(); \
instancTemp->SetInternalFieldCount(2); \
cls::JSCLSINFO.objTemplate = new Persistent<ObjectTemplate>(pJsIso, instancTemp); \
v8::Local<v8::Context> pCtx = pJsIso->GetCurrentContext();
//这个的区别是不能直接创建c对象,而是绑定一个已经存在的对象。
#define JSP_GLOBAL_CLASS(name,cls) \
v8::Isolate* pJsIso = Isolate::GetCurrent(); /*全局的每次都重新创建*/\
v8::HandleScope sc(pJsIso); \
v8::Local<v8::FunctionTemplate> xhrtemp = v8::FunctionTemplate::New(pJsIso); \
xhrtemp->SetClassName(Js_Str(pJsIso, name)); \
v8::Local<v8::ObjectTemplate> instancTemp = xhrtemp->InstanceTemplate(); \
instancTemp->SetInternalFieldCount(2); \
cls::JSCLSINFO.objTemplate = new Persistent<ObjectTemplate>(pJsIso, instancTemp); \
v8::Local<v8::Context> pCtx = pJsIso->GetCurrentContext();
#define JSP_REG_CONSTRUCTOR(cls,...) \
JSCClass<cls>::getInstance()->addConstructor(regConstructor<cls,##__VA_ARGS__>());
#define JSP_ADD_FIXED_PROPERTY(name,cls,val) \
instancTemp->Set(Js_Str(pJsIso, #name), __TransferToJs<decltype(val)>::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<cls>::reset);
#define JSP_INSTALL_G_CLASS(name,cls,inst) \
Local<Object> jsinst = instancTemp->NewInstance();\
jsinst->SetAlignedPointerInInternalField(0, inst); \
jsinst->SetAlignedPointerInInternalField(1, &cls::JSCLSINFO); \
Persistent<Object>* pPersist = new Persistent<Object>(pJsIso, jsinst);\
inst->mpJsThis = pPersist;\
pPersist->SetWeak(pPersist, JsDestructor1<cls>, 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<cls>(inst,false));
//添加一个只读属性。get是函数地址,funcplace是一个存放get和set函数地址的结构的指针
#define JSP_ADD_PROPERTY_RO(name,cls,get) \
static PropFuncInfo<decltype(&cls::get),decltype(&cls::get)> propFunc_R##cls##name(&cls::get); \
instancTemp->SetAccessor(Js_Str(pJsIso,#name), \
imp_JsGetProp<decltype(&cls::get),decltype(&cls::get)>::call,0, \
External::New(pJsIso, (void*)&propFunc_R##cls##name),v8::DEFAULT, v8::ReadOnly);
#define JSP_ADD_PROPERTY(name,cls,get,set) \
static PropFuncInfo<decltype(&cls::get),decltype(&cls::set)> propFunc_##cls##name(&cls::get, &cls::set); \
instancTemp->SetAccessor(Js_Str(pJsIso,#name), \
imp_JsGetProp<decltype(&cls::get),decltype(&cls::set)>::call,imp_JsSetProp<decltype(&cls::get),decltype(&cls::set)>::call, \
External::New(pJsIso, (void*)&propFunc_##cls##name));
#define JSP_GLOBAL_START1() \
v8::Isolate* pIso = v8::Isolate::GetCurrent(); \
v8::HandleScope sc(pIso); \
v8::Local<v8::Context> pCtx = pIso->GetCurrentContext(); \
v8::Local<v8::Object> 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<Value>& args, int num);
/////////////////////////////////////////////////////////
//回调的偏特化
//没有参数
template<typename Cls, typename R>
struct imp_JS2CFunc<R(Cls::*)(void)> {
typedef R(Cls::*funcType)(void);
static void call(const FunctionCallbackInfo<Value>& args) {
void* pExData = External::Cast(*args.Data())->Value();
//FuncInfo<funcType>* funcInfo = (FuncInfo<funcType>*)(&pExData);
FuncInfo<funcType>* funcInfo = (FuncInfo<funcType>*)pExData;
Local<Object> pthis = args.This();
JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1);
if (!IsSubClass<Cls>(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<R>((pObj->*funcInfo->func)()));
}
};
#define JS2CCALL_INIT \
void* pExData = External::Cast(*args.Data())->Value();\
FuncInfo<funcType>* funcInfo = (FuncInfo<funcType>*)pExData;\
Local<Object> pthis = args.This();
#define JS2CCALL_GET_COBJ \
JsObjClassInfo* id = (JsObjClassInfo*)pthis->GetAlignedPointerFromInternalField(1);\
if (!IsSubClass<Cls>(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<P1>::ToCpp(args[0]);
#define JS2CCALL_GET_PARAMS2 \
if(!checkJSToCArgs(args,2))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);
#define JS2CCALL_GET_PARAMS3 \
if(!checkJSToCArgs(args,3))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);
#define JS2CCALL_GET_PARAMS4 \
if(!checkJSToCArgs(args,4))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);
#define JS2CCALL_GET_PARAMS5 \
if(!checkJSToCArgs(args,5))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);
#define JS2CCALL_GET_PARAMS6 \
if(!checkJSToCArgs(args,6))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);
#define JS2CCALL_GET_PARAMS7 \
if(!checkJSToCArgs(args,7))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);\
P7 p7 = __TransferToCpp<P7>::ToCpp(args[6]);
#define JS2CCALL_GET_PARAMS8 \
if(!checkJSToCArgs(args,8))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);\
P7 p7 = __TransferToCpp<P7>::ToCpp(args[6]);\
P8 p8 = __TransferToCpp<P8>::ToCpp(args[7]);
#define JS2CCALL_GET_PARAMS9 \
if(!checkJSToCArgs(args,9))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);\
P7 p7 = __TransferToCpp<P7>::ToCpp(args[6]);\
P8 p8 = __TransferToCpp<P8>::ToCpp(args[7]);\
P9 p9 = __TransferToCpp<P9>::ToCpp(args[8]);
#define JS2CCALL_GET_PARAMS10 \
if(!checkJSToCArgs(args,10))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);\
P7 p7 = __TransferToCpp<P7>::ToCpp(args[6]);\
P8 p8 = __TransferToCpp<P8>::ToCpp(args[7]);\
P9 p9 = __TransferToCpp<P9>::ToCpp(args[8]);\
P10 p10 = __TransferToCpp<P9>::ToCpp(args[9]);
#define JS2CCALL_GET_PARAMS11 \
if(!checkJSToCArgs(args,11))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);\
P7 p7 = __TransferToCpp<P7>::ToCpp(args[6]);\
P8 p8 = __TransferToCpp<P8>::ToCpp(args[7]);\
P9 p9 = __TransferToCpp<P9>::ToCpp(args[8]);\
P10 p10 = __TransferToCpp<P10>::ToCpp(args[9]);\
P11 p11 = __TransferToCpp<P11>::ToCpp(args[10]);
#define JS2CCALL_GET_PARAMS12 \
if(!checkJSToCArgs(args,12))return;\
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);\
P4 p4 = __TransferToCpp<P4>::ToCpp(args[3]);\
P5 p5 = __TransferToCpp<P5>::ToCpp(args[4]);\
P6 p6 = __TransferToCpp<P6>::ToCpp(args[5]);\
P7 p7 = __TransferToCpp<P7>::ToCpp(args[6]);\
P8 p8 = __TransferToCpp<P8>::ToCpp(args[7]);\
P9 p9 = __TransferToCpp<P9>::ToCpp(args[8]);\
P10 p10 = __TransferToCpp<P10>::ToCpp(args[9]);\
P11 p11 = __TransferToCpp<P11>::ToCpp(args[10]);\
P12 p12 = __TransferToCpp<P12>::ToCpp(args[11]);
//一个参数
template<typename Cls, typename R, typename P1 >
struct imp_JS2CFunc<R(Cls::*)(P1)> {
typedef R(Cls::*funcType)(P1);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS1;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1)));
resetJsStrBuf();
}
};
//2
template<typename Cls, typename R, typename P1, typename P2 >
struct imp_JS2CFunc<R(Cls::*)(P1, P2)> {
typedef R(Cls::*funcType)(P1, P2);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS2;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2)));
resetJsStrBuf();
}
};
//3
template<typename Cls, typename R, typename P1, typename P2, typename P3 >
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3)> {
typedef R(Cls::*funcType)(P1, P2, P3);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS3;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3)));
resetJsStrBuf();
}
};
//4
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4 >
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS4;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4)));
resetJsStrBuf();
}
};
//5
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4, P5)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4, P5);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS5;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4, p5)));
resetJsStrBuf();
}
};
//6
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4, P5, P6)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS6;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6)));
resetJsStrBuf();
}
};
//7
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4, P5, P6, P7)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS7;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7)));
resetJsStrBuf();
}
};
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS8;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8)));
resetJsStrBuf();
}
};
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS9;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9)));
resetJsStrBuf();
}
};
template<typename Cls, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>
struct imp_JS2CFunc<R(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)> {
typedef R(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS12;
args.GetReturnValue().Set(ToJSValue<R>((pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)));
resetJsStrBuf();
}
};
//下面是void的,没想到好办法
//没有参数
template<typename Cls>
struct imp_JS2CFunc<void(Cls::*)(void)> {
typedef void(Cls::*funcType)(void);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
(pObj->*funcInfo->func)();
}
};
//一个参数
template< typename Cls, typename P1 >
struct imp_JS2CFunc<void(Cls::*)(P1)> {
typedef void(Cls::*funcType)(P1);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS1;
(pObj->*(funcInfo->func))(p1);
resetJsStrBuf();
}
};
//2
template<typename Cls, typename P1, typename P2 >
struct imp_JS2CFunc<void(Cls::*)(P1, P2)> {
typedef void(Cls::*funcType)(P1, P2);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS2;
(pObj->*funcInfo->func)(p1, p2);
resetJsStrBuf();
}
};
//3
template<typename Cls, typename P1, typename P2, typename P3 >
struct imp_JS2CFunc<void(Cls::*)(P1, P2, P3)> {
typedef void(Cls::*funcType)(P1, P2, P3);
static void call(const FunctionCallbackInfo<Value>& 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<void(Cls::*)(P1, P2, P3, P4)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4);
static void call(const FunctionCallbackInfo<Value>& 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<void(Cls::*)(P1, P2, P3, P4, P5)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5);
static void call(const FunctionCallbackInfo<Value>& 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<void(Cls::*)(P1, P2, P3, P4, P5, P6)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6);
static void call(const FunctionCallbackInfo<Value>& 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<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS7;
(pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7);
resetJsStrBuf();
}
};
//9
template<typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
struct imp_JS2CFunc<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_COBJ;
JS2CCALL_GET_PARAMS9;
(pObj->*funcInfo->func)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
resetJsStrBuf();
}
};
template<typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
struct imp_JS2CFunc<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10);
static void call(const FunctionCallbackInfo<Value>& 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<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11);
static void call(const FunctionCallbackInfo<Value>& 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<typename Cls, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>
struct imp_JS2CFunc<void(Cls::*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)> {
typedef void(Cls::*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12);
static void call(const FunctionCallbackInfo<Value>& 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<void(*)(void)> {
typedef void(*funcType)(void);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
funcInfo->func();
}
};
template<typename R>//R(void)
struct imp_JS2CFunc<R(*)(void)> {
typedef R(*funcType)(void);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func()));
}
};
template<typename R, typename P1>//R(p1)
struct imp_JS2CFunc<R(*)(P1)> {
typedef R(*funcType)(P1);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS1;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1)));
resetJsStrBuf();
}
};
template<typename R, typename P1>//const R(p1)
struct imp_JS2CFunc<const R(*)(P1)> {
typedef const R(*funcType)(P1);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS1;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1)));
resetJsStrBuf();
}
};
template<typename P1>
struct imp_JS2CFunc<void(*)(P1)> {//void(p1)
typedef void(*funcType)(P1);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS1;
funcInfo->func(p1);
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2>//R(p1,p2)
struct imp_JS2CFunc<R(*)(P1, P2)> {
typedef R(*funcType)(P1, P2);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS2;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2)));
resetJsStrBuf();
}
};
template<typename P1, typename P2>//void(p1,p2)
struct imp_JS2CFunc<void(*)(P1, P2)> {
typedef void(*funcType)(P1, P2);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS2;
funcInfo->func(p1, p2);
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3>//3
struct imp_JS2CFunc<R(*)(P1, P2, P3)> {
typedef R(*funcType)(P1, P2, P3);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS3;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3)));
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4>//4
struct imp_JS2CFunc<R(*)(P1, P2, P3, P4)> {
typedef R(*funcType)(P1, P2, P3, P4);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS4;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3, p4)));
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>//5
struct imp_JS2CFunc<R(*)(P1, P2, P3, P4, P5)> {
typedef R(*funcType)(P1, P2, P3, P4, P5);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS5;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3, p4, p5)));
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>//6
struct imp_JS2CFunc<R(*)(P1, P2, P3, P4, P5, P6)> {
typedef R(*funcType)(P1, P2, P3, P4, P5, P6);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS6;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3, p4, p5, p6)));
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>//7
struct imp_JS2CFunc<R(*)(P1, P2, P3, P4, P5, P6, P7)> {
typedef R(*funcType)(P1, P2, P3, P4, P5, P6, P7);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS7;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3, p4, p5, p6, p7)));
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>//8
struct imp_JS2CFunc<R(*)(P1, P2, P3, P4, P5, P6, P7, P8)> {
typedef R(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS8;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8)));
resetJsStrBuf();
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>//9
struct imp_JS2CFunc<R(*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)> {
typedef R(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS9;
args.GetReturnValue().Set(ToJSValue<R>(funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8, p9)));
resetJsStrBuf();
}
};
//void
template< typename P1, typename P2, typename P3>//3
struct imp_JS2CFunc<void(*)(P1, P2, P3)> {
typedef void(*funcType)(P1, P2, P3);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS3;
funcInfo->func(p1, p2, p3);
resetJsStrBuf();
}
};
template<typename P1, typename P2, typename P3, typename P4>//4
struct imp_JS2CFunc<void(*)(P1, P2, P3, P4)> {
typedef void(*funcType)(P1, P2, P3, P4);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS4;
funcInfo->func(p1, p2, p3, p4);
resetJsStrBuf();
}
};
template<typename P1, typename P2, typename P3, typename P4, typename P5>//5
struct imp_JS2CFunc<void(*)(P1, P2, P3, P4, P5)> {
typedef void(*funcType)(P1, P2, P3, P4, P5);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS5;
funcInfo->func(p1, p2, p3, p4, p5);
resetJsStrBuf();
}
};
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>//6
struct imp_JS2CFunc<void(*)(P1, P2, P3, P4, P5, P6)> {
typedef void(*funcType)(P1, P2, P3, P4, P5, P6);
static void call(const FunctionCallbackInfo<Value>& 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<void(*)(P1, P2, P3, P4, P5, P6, P7)> {
typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS7;
funcInfo->func(p1, p2, p3, p4, p5, p6, p7);
resetJsStrBuf();
}
};
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>//8
struct imp_JS2CFunc<void(*)(P1, P2, P3, P4, P5, P6, P7, P8)> {
typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS8;
funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8);
resetJsStrBuf();
}
};
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>//9
struct imp_JS2CFunc<void(*)(P1, P2, P3, P4, P5, P6, P7, P8, P9)> {
typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
static void call(const FunctionCallbackInfo<Value>& args) {
JS2CCALL_INIT;
JS2CCALL_GET_PARAMS9;
funcInfo->func(p1, p2, p3, p4, p5, p6, p7, p8, p9);
resetJsStrBuf();
}
};
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10, typename P11, typename P12>//12
struct imp_JS2CFunc<void(*)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)> {
typedef void(*funcType)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12);
static void call(const FunctionCallbackInfo<Value>& 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<Value>& args) { throw "not implemented"; }
virtual uint16_t getNumArgs() = 0;
};
#define JS2CCONSTRUCTOR_GET_PARAMS1 \
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);
#define JS2CCONSTRUCTOR_GET_PARAMS2 \
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);
#define JS2CCONSTRUCTOR_GET_PARAMS3 \
P1 p1 = __TransferToCpp<P1>::ToCpp(args[0]);\
P2 p2 = __TransferToCpp<P2>::ToCpp(args[1]);\
P3 p3 = __TransferToCpp<P3>::ToCpp(args[2]);
template<typename Cls>
struct JSCConstructor0 : public IJSCCallback {
virtual void* constructor(const FunctionCallbackInfo<Value>& args) {
return new Cls();
}
virtual uint16_t getNumArgs() { return 0; }
};
template<typename Cls>
IJSCCallback* regConstructor() {
return new JSCConstructor0<Cls>();
}
template<typename Cls, typename P1>
struct JSCConstructor1 :public IJSCCallback {
virtual void* constructor(const FunctionCallbackInfo<Value>& args) {
JS2CCONSTRUCTOR_GET_PARAMS1;
return new Cls(p1);
}
virtual uint16_t getNumArgs() { return 1; }
};
template<typename Cls, typename P1>
IJSCCallback* regConstructor() {
return new JSCConstructor1<Cls, P1>();
}
template<typename Cls, typename P1, typename P2>
struct JSCConstructor2 :public IJSCCallback {
virtual void* constructor(const FunctionCallbackInfo<Value>& args) {
JS2CCONSTRUCTOR_GET_PARAMS2;
return new Cls(p1, p2);
}
virtual uint16_t getNumArgs() { return 2; }
};
template<typename Cls, typename P1, typename P2, typename P3>
struct JSCConstructor3 :public IJSCCallback {
virtual void* constructor(const FunctionCallbackInfo<Value>& args) {
JS2CCONSTRUCTOR_GET_PARAMS3;
return new Cls(p1, p2, p3);
}
virtual uint16_t getNumArgs() { return 3; }
};
template<typename Cls, typename P1, typename P2>
IJSCCallback* regConstructor() {
return new JSCConstructor2<Cls, P1, P2>();
}
template<typename Cls, typename P1, typename P2, typename P3>
IJSCCallback* regConstructor() {
return new JSCConstructor3<Cls, P1, P2, P3>();
}
template<typename T>
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<T> instance;
return &instance;
}
void addConstructor(IJSCCallback* constructor) {
m_Constructor.add(constructor);
}
static void reset() {
JSCClass<T>::getInstance()->_reset();
}
static void JsConstructor(const FunctionCallbackInfo<Value>& args) {
if (!args.IsConstructCall()) {
printf("not a Construct Call)\n");
return;
}
IJSCCallback *pfn = JSCClass<T>::getInstance()->m_Constructor.get(args.Length());
Isolate* pIso = Isolate::GetCurrent();
HandleScope handle_scope(pIso);
Local<Object> 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<Object>* pPersist = new Persistent<Object>(pIso, pthis);
obj->mpJsThis = pPersist;
pPersist->SetWeak(pPersist, JsDestructor<T>, 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<RESETFUNC> allCls;
void resetAllRegClass() {
for (int i = 0, sz = allCls.size(); i < sz; i++) {
allCls[i]();
}
allCls.clear();
}
private:
static thread_local JSClassMgr __Ins;
};
}
#endif