Jx9 虚拟机

 一、Jx9 虚拟机的生命周期
  1. 加载 Jx9 脚本 jx9_compile() 或 jx9_compile_file(),加载编译成功后,Jx9 引擎将自动创建一个实例 (jx9_vm) 并且返回指向此虚拟机的指针用于后续调用。
  2. 如加载编译 Jx9 脚本时出现问题,也就是编译时出错,可调用jx9_config()方法获取编译错误原因。
  3. (可选) jx9_vm_config(),向脚本中传递参数(JX9_VM_CONFIG_ARGV_ENTRY)及注册虚拟机与脚本语言之间数据交互的回调函数(JX9_VM_CONFIG_OUTPUT)。
  4. (可选)jx9_create_function() ,用于注册可以从 Jx9 脚本调用的外部函数(通常是 C/C++ 实现的函数)。
  5. 执行Jx9 脚本 ,调用 jx9_vm_exec() 执行 Jx9 程序。
  6. jx9_vm_extract_variable() 用于提取在 Jx9 脚本中声明的另一个变量的内容。
  7. 重置虚拟机 使用 jx9_vm_reset()的虚拟机,然后返回到步骤 5,执行此操作零次或多次。
  8. 使用 jx9_vm_release() 销毁虚拟机。

 

二、Jx9 C/C++ API 参考

  Jx9 - 可嵌入的脚本引擎 (symisc.net)

 

三、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;
}

posted on 2023-03-28 18:55  百足Coder  阅读(96)  评论(0编辑  收藏  举报

导航