3.2 KiB
3.2 KiB
QuickJS C/JS 交互示例
本项目演示了 C 和 JavaScript 之间的各种交互方式。
编译
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
运行示例
简单示例 (simple_demo)
.\build\bin\Release\simple_demo.exe
简单示例包含:
- 基本的 JavaScript 表达式求值
- 字符串操作
- JavaScript 函数调用
- 从 JavaScript 调用 C 函数
完整示例 (demo)
.\build\bin\Release\demo.exe
完整示例包含:
- 基本 JavaScript 执行 - 执行简单的 JS 表达式和函数
- 从 C 调用 JavaScript 函数 - 调用 JS 函数并处理返回值
- 从 JavaScript 调用 C 函数 - 注册 C 函数供 JS 调用
- 数据类型转换 - 在 C 和 JS 之间转换各种数据类型
- 对象操作 - 创建和操作 JavaScript 对象
- 数组操作 - 创建和操作 JavaScript 数组
- 异常处理 - 处理 JS 和 C 中的异常
- 内存管理 - JSValue 的引用计数和垃圾回收
- 标准库模块 - 使用 std 和 os 模块
- 自定义模块 - 创建和使用自定义 JS 模块
关键 API
初始化
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
js_std_add_helpers(ctx, argc, argv);
执行 JavaScript
JSValue result = JS_Eval(ctx, "1 + 2", 5, "<eval>", JS_EVAL_TYPE_GLOBAL);
注册 C 函数
JSValue func = JS_NewCFunction(ctx, my_c_function, "funcName", argCount);
JS_SetPropertyStr(ctx, global, "funcName", func);
数据类型转换
// C 到 JS
JSValue val = JS_NewInt32(ctx, 42);
JSValue str = JS_NewString(ctx, "Hello");
// JS 到 C
double num;
JS_ToFloat64(ctx, &num, js_value);
const char *str = JS_ToCString(ctx, js_value);
JS_FreeCString(ctx, str);
内存管理
JSValue val = JS_NewString(ctx, "test");
JSValue val2 = JS_DupValue(ctx, val); // 增加引用
JS_FreeValue(ctx, val); // 释放引用
JS_FreeValue(ctx, val2); // 最后一个引用被释放
异常处理
JSValue exception = JS_GetException(ctx);
if (!JS_IsUndefined(exception)) {
// 处理异常
}
JS_FreeValue(ctx, exception);
项目结构
quickjs-prj/
├── yps-quickjs/ # QuickJS 库源码
│ ├── quickjs.c/h # 核心 API
│ ├── quickjs-libc.c/h # 标准库扩展
│ └── CMakeLists.txt # 库构建配置
├── main.c # 完整示例
├── simple_demo.c # 简单示例
├── CMakeLists.txt # 主项目构建配置
└── build/ # 构建输出目录
├── lib/ # 静态库
└── bin/ # 可执行文件
集成到你的项目
在你的 CMakeLists.txt 中添加:
add_subdirectory(path/to/yps-quickjs)
target_link_libraries(your_target PRIVATE ypqjs)
target_include_directories(your_target PRIVATE path/to/yps-quickjs)
注意事项
- 栈大小:Windows 上默认需要 8MB 栈大小
- 编码:源文件使用 UTF-8 编码以支持中文字符
- 内存管理:及时释放 JSValue 以避免内存泄漏
- 异常处理:执行 JS 代码后检查异常
- 线程安全:每个线程需要独立的 JSRuntime 和 JSContext