int Interface::UserInvoke(JNIEnv *jniEnv, Handle<Object> target, int opIdx, jobjectArray jArgs, jobject *jResult) { HandleScope scope; TryCatch tryCatch; Operation *op = operations->addr(opIdx); int result = OK; for(int i = 0; result == OK && i < op->argCount; i++) { result = conv->ToV8Value(jniEnv, jniEnv->GetObjectArrayElement(jArgs, i), op->argTypes[i], &op->vArgs[i]); } if(result == OK) { Handle<Value> vRes; if(target->IsFunction() && parent == 0 && operations->getLength() == 1) { /* invoke as function if target is a function, and interface delcares only one operation */ vRes = (Handle<Function>::Cast(target))->Call(target, op->argCount, op->vArgs); } else { /* locate the method and invoke that */ Handle<Value> vMethod = target->Get(op->name); if(!vMethod.IsEmpty() && vMethod->IsFunction()) { vRes = Handle<Function>::Cast(vMethod)->Call(target, op->argCount, op->vArgs); } } if(!vRes.IsEmpty() && op->type != TYPE_UNDEFINED) { jobject ob; result = conv->ToJavaObject(jniEnv, vRes, op->type, &ob); if(result == OK) { *jResult = ob; } } } if(tryCatch.HasCaught()) { result = ErrorJS; tryCatch.Reset(); } return result; }
int Interface::UserSet(JNIEnv *jniEnv, Handle<Object> target, int attrIdx, jobject jVal) { HandleScope scope; TryCatch tryCatch; Attribute *attr = attributes->addr(attrIdx); Handle<Value> val; int result = conv->ToV8Value(jniEnv, jVal, attr->type, &val); if(result == OK) { target->Set(attr->name, val); } if(tryCatch.HasCaught()) { result = ErrorJS; tryCatch.Reset(); } return result; }
int Interface::UserGet(JNIEnv *jniEnv, Handle<Object> target, int attrIdx, jobject *jVal) { HandleScope scope; TryCatch tryCatch; Attribute *attr = attributes->addr(attrIdx); Handle<Value> val = target->Get(attr->name); if(tryCatch.HasCaught()) { tryCatch.Reset(); return ErrorJS; } jobject ob; int result = conv->ToJavaObject(jniEnv, val, attr->type, &ob); if(result == OK) { *jVal = ob; } return result; }
void test1(cv::Shell & shell) { using namespace v8; HandleScope scope; bind_MyType( shell.Global() ); if(1) { Handle<Function> hf = FunctionTemplate::New(test1_callback)->GetFunction(); Handle<Value> args[] = { Integer::New(3), Number::New(5.1), Undefined() }; CERR << "Calling binding function...\n"; TryCatch catcher; hf->Call( shell.Context()->Global(), 3, args ); catcher.Reset(); CERR << "Returned from binding function.\n"; } else { BoundNative::SetupBindings( shell.Global() ); } char const * extScr = "./test.js"; CERR << "Calling external script ["<<extScr<<"]...\n"; if(1) { Local<Object> global( shell.Context()->Global() ); assert( ! global.IsEmpty() ); Local<Function> jf( Function::Cast( *(global->Get(JSTR("load"))) ) ); assert( ! jf.IsEmpty() ); cv::CallForwarder<1>::Call( global, jf, extScr ); } else if(1) { shell.ExecuteFile( extScr ); } CERR << "Returned from external script\n"; }
//事件循环 //TAGG核心代码程序 static void eventLoop (typeThread* thread) { thread->isolate->Enter(); //进入 isolate thread->context= Context::New(); //创建一个sandbox沙箱用来执行js代码,他的上下文将有他自己控制 thread->context->Enter(); //进入这个上下文 { HandleScope scope1; //返回这个分离的沙箱内的全局对象 //Local< Object > Global () Local<Object> global= thread->context->Global(); global->Set(String::NewSymbol("_Global"), global); //将puts方法设置到全局中去,代替console.log Handle<Object> console_obj = Object::New(); console_obj->Set(String::New("log"), FunctionTemplate::New(Puts)->GetFunction()); global->Set(String::New("console"), console_obj); global->Set(String::New("require"), FunctionTemplate::New(require_file)->GetFunction(), ReadOnly); //定义一个thread对象到全局变量中 Local<Object> threadObject= Object::New(); global->Set(String::NewSymbol("thread"), threadObject); //设置这个全局对象thread的id和emit属性 threadObject->Set(String::NewSymbol("id"), Number::New(thread->id)); threadObject->Set(String::NewSymbol("emit"), FunctionTemplate::New(threadEmit)->GetFunction()); threadObject->Set(String::NewSymbol("end"), FunctionTemplate::New(threadEnd)->GetFunction()); threadObject->Set(String::New("_TAGG_RES"), Undefined()); //返回的全局变量字符串 //将global对象放入全局global中,每次都会初始化 Handle<Object> user_global = Object::New(); global->Set(String::NewSymbol("global"), user_global); global->Set(String::NewSymbol("Global"), user_global); //让threadObject继承event接口 Local<Object> dispatchEvents= Script::Compile(String::New(kEvents_js))->Run()->ToObject()->CallAsFunction(threadObject, 0, NULL)->ToObject(); //获得下个事件循环的函数 Local<Object> dispatchNextTicks= Script::Compile(String::New(kThread_nextTick_js))->Run()->ToObject(); //获得thread_nextTick.js中定义的 next回调函数的数组 Local<Array> _ntq= (v8::Array*) *threadObject->Get(String::NewSymbol("_ntq")); double nextTickQueueLength= 0; //事件循环次数 long int ctr= 0; //SetFatalErrorHandler(FatalErrorCB); while (!thread->sigkill) { //当线程的信号不为kill时,则循环执行下面代码 typeJob* job; typeQueueItem* qitem; {//while循环代码块 HandleScope scope2; //v8的TryCatch类, //一个外部的异常控制类 TryCatch onError; String::Utf8Value* str;//临时保存js源代码的指针 Local<String> source; //保存js源代码字符串 Local<Script> script; //保存js源代码 Local<Value> resultado; //保存js源代码执行的return 结果值 while ((qitem= queue_pull(&thread->inQueue))) { //当队列中有项目时,循环执行如下代码 job= (typeJob*) qitem->asPtr; //队列中的任务 if ((++ctr) > 2e3) { //如果ctr 大于 2*10的3次方 ctr= 0; V8::IdleNotification(); //强制V8进行GC while(!V8::IdleNotification()) {}; } if (job->jobType == kJobTypeEval) { //如果执行的任务 //Ejecutar un texto if (job->typeEval.useStringObject) { //如果是eval方法传入的参数进来的 str= job->typeEval.scriptText_StringObject; source= String::New(**str, (*str).length()); delete str; //删除str指针 } else { //如果是load js 文件进来的 source= String::New(job->typeEval.scriptText_CharPtr);//创建js源代码string, free(job->typeEval.scriptText_CharPtr); //释放 } script= Script::New(source); //将源代码字符串,转存为js代码 //这里进行判断,如果上下问里的js代码执行抛出了异常,则本次循环将不执行js代码了 //将global对象放入全局global中,每次都会初始化 Handle<Object> user_global = Object::New(); global->Set(String::NewSymbol("global"), user_global); global->Set(String::NewSymbol("Global"), user_global); if (!onError.HasCaught()){ //如果没有错误 //Local<Object> obj = job->buffer->Clone(); //resultado = String::NewSymbol("id"); //将char* 的job->buf_ptr又转换为Buffer指针 //node::Buffer *buf = node::Buffer::New(job->buf_ptr, job->buf_len); //Local<Object> buf_obj = External::Wrap(buf)->ToObject(); threadObject->Set(String::New("_TAGG_RES"), Undefined()); //返回的全局变量字符串 Local<Object> buf_obj = Object::New(); if(job->buf_ptr){ buf_obj->SetHiddenValue(String::New("buffer"), String::New(job->buf_ptr, job->buf_len)); buf_obj->SetHiddenValue(String::New("isBuffer"),Number::New(1)); } else{ buf_obj->SetHiddenValue(String::New("isBuffer"),Number::New(0)); } buf_obj->Set(String::NewSymbol("toString"), FunctionTemplate::New(Buffer_toString)->GetFunction()); threadObject->Set(String::NewSymbol("buffer"), buf_obj); global->Set(String::NewSymbol("__dirname"), String::New(**job->__dirname)); global->SetPointerInInternalField(0, job->__dirname); script->Run(); //执行js代码,返回值为 resultado resultado = threadObject->Get(String::New("_TAGG_RES")); }//如果没有错误 if (_ntq->Length() && !onError.HasCaught()) { //当有错误时,不执行异步 if ((++ctr) > 2e3) { ctr= 0; V8::IdleNotification();//强制GC } resultado = dispatchNextTicks->CallAsFunction(global, 0, NULL); //调用线程内的 nexttick } if (job->typeEval.tiene_callBack) { //如果执行任务具有回调函数 //如果有错误,则 job->typeEval.error 是1,否则为0; job->typeEval.error= onError.HasCaught() ? 1 : 0; if(job->typeEval.error){ _ntq= Array::New(); } //如果有异常,则返回值 resultado 为异常内容,否则为函数返回内容 job->typeEval.resultado= new String::Utf8Value(job->typeEval.error ? onError.Exception() : threadObject->Get(String::New("_TAGG_RES"))); //执行完毕,将qtiem项丢入线程的出列队列 queue_push(qitem, &thread->outQueue); // wake up callback //丢入异步队列 uv_async_send(&thread->async_watcher); } else { //如果没有回调函数,则把改item丢入闲置任务队列 queue_push(qitem, freeJobsQueue); } if (onError.HasCaught()){ nextTickQueueLength= 1; onError.Reset(); //如果此次执行有错误,则清空 } else{ nextTickQueueLength= resultado->NumberValue(); } }//如果执行的任务 else if (job->jobType == kJobTypeEvent) { //如果是事件的任务 //Emitir evento. Local<Value> args[2]; //定义一个数组长度为2,保存 Local<Value> 类型的值 str= job->typeEvent.eventName; //获得事件名字 args[0]= String::New(**str, (*str).length()); //数组第一个保存event事件的名字,保存为local<string>类型 delete str; Local<Array> array= Array::New(job->typeEvent.length); args[1]= array; //设置参数长度 int i= 0; while (i < job->typeEvent.length) { //将参数保存入Local<Array> str= job->typeEvent.argumentos[i]; array->Set(i, String::New(**str, (*str).length())); delete str; i++; } free(job->typeEvent.argumentos); //释放任务的 typeEvent 内存 queue_push(qitem, freeJobsQueue); //将本项丢入闲置任务队列 dispatchEvents->CallAsFunction(global, 2, args); //执行回调函数,并且加入参数 }//如果是事件的任务 }//while2 结束 /* if (_ntq->Length()) { //执行异步 if ((++ctr) > 2e3) { ctr= 0; V8::IdleNotification();//强制GC } resultado = dispatchNextTicks->CallAsFunction(global, 0, NULL); //调用线程内的 nexttick if (onError.HasCaught()) { //如果有错误 nextTickQueueLength= 1; //nexttick队列长度为1 onError.Reset(); } else { nextTickQueueLength= resultado->NumberValue(); } } */ if (thread->inQueue.length) continue; if (thread->sigkill) break; //如果收到线程杀死信号,条春循环 pthread_mutex_lock(&thread->IDLE_mutex); //锁住线程 if (!thread->inQueue.length) { //如果线程的入队列长度为0 thread->IDLE= 1; //则把线程设置为闲置 pthread_cond_wait(&thread->IDLE_cv, &thread->IDLE_mutex); //休眠线程 thread->IDLE= 0; } pthread_mutex_unlock(&thread->IDLE_mutex); //解锁线程 }//while 结束 } thread->context.Dispose(); //摧毁上下文 } }