脚本有需求,需要实现一个forceStop方法供脚本主动中断。
在LuaJava框架中,Lua脚本从入口LuaState.pcall方法开始,会一直阻塞当前Java线程的运行,直到Lua脚本执行结束。
实现中断退出使用的是Lua虚拟机的lua_error方法,
LUA_API int (lua_error) (lua_State *L); 复制代码
然后就是找到该方法的调用时机。
不能随便找个地方就直接使用lua_error来中断pcall,这样会导致Java层出现各种莫名其妙的异常使得整个程序崩溃。
选择在luajava.cpp的luaJavaFunctionCall方法中修改,所有通过框架注册的自定义Java函数都会走到这里,
int luaJavaFunctionCall(lua_State *L) {
...
/* the Object must be an instance of the JavaFunction class */
if (javaEnv->IsInstanceOf(*obj, java_function_class) ==
JNI_FALSE) {
fprintf(stderr, "Called Java object is not a JavaFunction/n");
return 0;
}
ret = javaEnv->CallIntMethod(*obj, java_function_method,(jlong)L);
javaEnv->CallVoidMethod(*obj, java_function_method_cleanup);
...
checkLuaStop(L);
}
复制代码
在方法末尾增加个检查退出函数 checkLuaStop(LuaState* L),通过全局标识位forceStop来判断是否需要退出,顺便给Lua脚本一个结束回调,最后才抛出lua_error结束。
FUNC_EXPORT void checkLuaStop(lua_State *L) {
if (forceStop == 1) {
/*在用户主动终止脚本运行之前执行的回调函数 */
LOGE("beforeUserExit");
lua_getglobal(L, "beforeUserExit");
lua_call(L, 0, 0);
lua_pop(L, 1);
lua_pushstring(L, "lua force close!");
lua_error(L);
}
}
复制代码
forceStop的值由自定义注册的forceStop函数控制的。
void jni_forceStop(JNIEnv *env, jobject jobj, jobject cptr) {
forceStop = 1;
}
jboolean jni_isClosing(JNIEnv *env, jobject jobj, jobject cptr) {
if (forceStop == 1) {
return JNI_TRUE;
} else {
return JNI_FALSE;
}
}
复制代码