1. 虚拟机如何启动

启动流程 代码示图
evm_start evm_start

1.1 注册虚拟机API

  1. // 注册平台相关的虚拟机API
  2. evm_register_malloc((intptr_t)vm_malloc);
  3. evm_register_free((intptr_t)vm_free);
  4. evm_register_file_load((intptr_t)vm_load);
  5. evm_register_print((intptr_t)printf);
  • 注册外部内存申请接口 evm_register_malloc
  1. /**
  2. * @brief 外部内存申请接口
  3. * @param size, 申请内存大小
  4. * @return 内存成功分配的对象指针
  5. */
  6. void * vm_malloc(int size)
  7. {
  8. void * m = malloc(size);
  9. if(m) memset(m, 0 ,size);
  10. return m;
  11. }
  • 注册外部内存释放接口 evm_register_free
  1. /**
  2. * @brief 外部内存释放接口
  3. * @param mem, 需要释放的对象指针
  4. * @return
  5. */
  6. void vm_free(void * mem)
  7. {
  8. if(mem) free(mem);
  9. }
  • 注册脚本加载接口 evm_register_file_load
  1. /**
  2. * @brief 加载main运行脚本和加模块脚本
  3. * @param e, 虚拟机对象
  4. * @param path, 脚本路径
  5. * @param type, EVM_LOAD_MAIN代表main运行脚本,非EVM_LOAD_MAIN代表加载模块
  6. * @return
  7. */
  8. const char * vm_load(evm_t * e, char * path, int type)
  9. {
  10. int file_name_len = strlen(path) + 1;
  11. char* buffer = NULL;
  12. if(type == EVM_LOAD_MAIN){
  13. char * module_name = evm_malloc(file_name_len);
  14. if( !module_name ) return NULL;
  15. sprintf(module_name, "%s", path);
  16. sprintf(e->file_name, "%s", path);
  17. buffer = open(e, module_name);
  18. evm_free(module_name);
  19. } else {
  20. for(int i=0; i< modules_paths_count; i++){
  21. int len = strlen(modules_paths[i]) + 1 + file_name_len;
  22. char* modules_path = evm_malloc(len);
  23. sprintf(modules_path, "%s/%s", modules_paths[i], path);
  24. sprintf(e->file_name, "%s", path);
  25. buffer = open(e, modules_path);
  26. evm_free(modules_path);
  27. if (buffer){
  28. break;
  29. }
  30. }
  31. if (!buffer){
  32. const char * module_path = "../../evm/test/eJS/%s";
  33. int file_name_len = strlen(module_path) + strlen(path) + 1;
  34. char * module_name = evm_malloc(file_name_len);
  35. sprintf(module_name, module_path, path);
  36. sprintf(e->file_name, "%s", path);
  37. buffer = open(e, module_name);
  38. evm_free(module_name);
  39. }
  40. }
  41. return buffer;
  42. }
  • 注册打印接口 evm_register_print
  1. // 标准的c语言printf接口
  2. printf

1.2 初始化虚拟机

用户自定义申请堆栈大小和最大加载模块个数,用户依据适配平台自定义分配

配置项 默认值 备注
heap_size 1000 1000 1024 堆大小
stack_size 10000 * 1024 栈大小
module_size 10 最大加载模块个数
  1. // 初始化虚拟机
  2. int32_t head_size = 10 *1000 * 1024;
  3. int32_t stack_size = 10000 * 1024;
  4. int32_t module_size = 10;
  5. evm_t * env = (evm_t*)malloc(sizeof(evm_t));
  6. memset(env, 0, sizeof(evm_t));
  7. int err = evm_init(env, head_size, stack_size, module_size, EVM_VAR_NAME_MAX_LEN, EVM_FILE_NAME_LEN);

1.3 加载虚拟机模块

根据项目需求,加载用户指定的模块

  1. // 加载ecma模块
  2. ecma_module(env, 10);

1.4 启动REPL调试

用户根据自身需求是否启动REPL模块,在线调试程序

  1. // 启动REPL调试
  2. if (argc == 1){
  3. help();
  4. evm_repl_run(env, 1000, EVM_LANG_JS);
  5. }

1.5 加载js/py/lua等脚本文件

加载入口main脚本文件

  1. err = evm_boot(env, argv[1]);
  2. if (err == ec_no_file){
  3. printf(QMAKE_TARGET": can't open file '%s': [Errno 2] No such file or directory\n", argv[1]);
  4. exit(1);
  5. }
  6. if(err) {return err;}

1.6 启动虚拟机

启动虚拟机,运行入口脚本

  1. // 启动虚拟机
  2. err = evm_start(env);

2. 完整的main.c示例文件

完整的main.c文件

  1. int main(int argc, char *argv[])
  2. {
  3. // 注册平台相关的虚拟机API
  4. evm_register_free((intptr_t)vm_free);
  5. evm_register_malloc((intptr_t)vm_malloc);
  6. evm_register_print((intptr_t)printf);
  7. evm_register_file_load((intptr_t)vm_load);
  8. // 初始化虚拟机
  9. int32_t head_size = 10 *1000 * 1024;
  10. int32_t stack_size = 10000 * 1024;
  11. int32_t module_size = 10;
  12. evm_t * env = (evm_t*)malloc(sizeof(evm_t));
  13. memset(env, 0, sizeof(evm_t));
  14. int err = evm_init(env, head_size, stack_size, module_size, EVM_VAR_NAME_MAX_LEN, EVM_FILE_NAME_LEN);
  15. // 加载ecma模块
  16. ecma_module(env, 10);
  17. // 启动REPL调试
  18. if (argc == 1){
  19. help();
  20. evm_repl_run(env, 1000, EVM_LANG_JS);
  21. }
  22. // 加载js/py/lua等脚本文件
  23. err = evm_boot(env, argv[1]);
  24. if (err == ec_no_file){
  25. printf(QMAKE_TARGET": can't open file '%s': [Errno 2] No such file or directory\n", argv[1]);
  26. exit(1);
  27. }
  28. if(err) {return err;}
  29. // 启动虚拟机
  30. err = evm_start(env);
  31. return err;
  32. }