Jx9 虚拟机
一、Jx9 虚拟机的生命周期
- 加载 Jx9 脚本 jx9_compile() 或 jx9_compile_file(),加载编译成功后,Jx9 引擎将自动创建一个实例 (jx9_vm) 并且返回指向此虚拟机的指针用于后续调用。
- 如加载编译 Jx9 脚本时出现问题,也就是编译时出错,可调用jx9_config()方法获取编译错误原因。
- (可选) jx9_vm_config(),向脚本中传递参数(JX9_VM_CONFIG_ARGV_ENTRY)及注册虚拟机与脚本语言之间数据交互的回调函数(JX9_VM_CONFIG_OUTPUT)。
- (可选)jx9_create_function() ,用于注册可以从 Jx9 脚本调用的外部函数(通常是 C/C++ 实现的函数)。
- 执行Jx9 脚本 ,调用 jx9_vm_exec() 执行 Jx9 程序。
- jx9_vm_extract_variable() 用于提取在 Jx9 脚本中声明的另一个变量的内容。
- 重置虚拟机 使用 jx9_vm_reset()的虚拟机,然后返回到步骤 5,执行此操作零次或多次。
- 使用 jx9_vm_release() 销毁虚拟机。
二、Jx9 C/C++ API 参考
三、Jx9 虚拟机编写
//判断Jx9脚本文件是否存在 bool exists_jx9(string strJx9File) { struct stat buffer = { 0 }; return (stat(strJx9File.c_str(), &buffer) == 0); }
//读取Jx9脚本文件 string read_jx9(string strJx9File) { string strRet = _T(""); size_t sJx9Size = 0; std::vector<char> vszBuffer; vszBuffer.clear(); std::shared_ptr<std::iostream> pJx9Script = std::make_shared<std::fstream>(strJx9File, std::ios::in | std::ios::binary); pJx9Script->seekg(0, ios::end); sJx9Size = pJx9Script->tellg(); pJx9Script->seekg(0); if (sJx9Size > 0) { vszBuffer.resize(sJx9Size); pJx9Script->read(&vszBuffer[0], sJx9Size); strRet.assign(vszBuffer.begin(), vszBuffer.end()); } return strRet; }
//打印错误日志 void jx9_log(jx9* pEngine, int nResult) { int nLen = 0; const char *zErrLog = nullptr; if (nResult != JX9_COMPILE_ERR) { return; } /* Extract error log */ jx9_config(pEngine, JX9_CONFIG_ERR_LOG, &zErrLog, &nLen); if (nLen > 0) { /* zErrLog is null terminated */ printf(zErrLog); printf("\n"); } }
//回调函数 int Jx9_callback( const void *pOutput, unsigned int nOutputLen, void *pUserData /* Unused */) { return JX9_OK; }
int main(int argc, char** argv) { int nRes = -1; string strError = _T(""); string strJx9File = _T(""); string strJx9Script = _T(""); if (argc < 2) { printf("参数不够!"); return 1; } printf("——————————Jx9 begin——————————\n"); strJx9File = string(argv[1]); jx9* pEngine = nullptr; /* JX9 engine handle*/ jx9_vm* pVm = nullptr; /* Compiled JX9 program */ c_jx9_fun jx9Fun; //判断Jx9脚本是否存在 if (!exists_jx9(strJx9File)) { strError = "Jx9 脚本文件不存在!"; goto main_end; } //读取Jx9脚本内容 strJx9Script = read_jx9(strJx9File); if (strJx9Script.empty()) { strError = "Jx9 脚本文件为空!"; goto main_end; } //初始化引擎 nRes = jx9_init(&pEngine); if (nRes != JX9_OK) { strError = "Jx9 引擎初始化失败!"; goto main_end; } //编译脚本 nRes = jx9_compile(pEngine, strJx9Script.c_str(), strJx9Script.length(), &pVm); if (nRes != JX9_OK) { // jx9_log(pEngine, nRes); strError = "Jx9 引擎编译脚本失败!"; goto main_end; } //注册回调函数 nRes = jx9_vm_config(pVm, JX9_VM_CONFIG_OUTPUT, Jx9_callback, /* Output Consumer callback */ 0 /* Callback private data */ ); if (nRes != JX9_OK) { strError = "Jx9 注册回调函数失败!"; goto main_end; } //开始执行 nRes = jx9_vm_exec(pVm, 0); if (nRes != JX9_OK) { strError = "Jx9 执行失败!"; goto main_end; } strError = "Jx9 执行成功!"; main_end: //释放 if (pVm) { jx9_vm_release(pVm); } if (pEngine) { jx9_release(pEngine); } jx9_lib_shutdown(); printf(strError.c_str()); return 1; }