You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过QuickJS从C语言调用CommonJS模块中的函数?

解决QuickJS访问CommonJS模块函数的问题

要在C/C++中通过QuickJS访问CommonJS模块内的函数,核心是利用QuickJS的模块加载能力,直接获取模块的导出对象,而非依赖全局作用域。具体步骤如下:

1. 以模块模式执行代码

使用JS_Eval时指定JS_EVAL_TYPE_MODULE参数,将CommonJS模块代码作为模块执行,此时返回的JSValue就是模块的命名空间对象。

2. 获取模块导出对象

模块的导出内容会挂载在模块对象的exports属性上,通过JS_GetPropertyStr即可获取导出对象。

3. 调用导出的函数

从导出对象中拿到目标函数后,就可以用JS_Call执行函数,参数和普通函数调用一致。

示例代码

/* 假设ctx是已初始化的有效JSContext */
const char *module_code = "module.exports = { add: (a, b) => a + b };";

// 以模块模式执行CommonJS代码
JSValue module_result = JS_Eval(ctx, module_code, strlen(module_code), "<module>", JS_EVAL_TYPE_MODULE);

// 异常检查:模块加载失败时处理
if (JS_IsException(module_result)) {
    JSValue err = JS_GetException(ctx);
    char *err_str = JS_ToCString(ctx, err);
    fprintf(stderr, "模块加载失败: %s\n", err_str);
    JS_FreeCString(ctx, err_str);
    JS_FreeValue(ctx, err);
    JS_FreeValue(ctx, module_result);
    return;
}

// 获取模块的exports对象
JSValue exports = JS_GetPropertyStr(ctx, module_result, "exports");

// 获取导出的add函数
JSValue add_func = JS_GetPropertyStr(ctx, exports, "add");

// 准备调用参数
JSValue arg1 = JS_NewInt32(ctx, 5);
JSValue arg2 = JS_NewInt32(ctx, 3);
JSValue args[] = {arg1, arg2};

// 调用函数,this绑定到exports对象
JSValue call_result = JS_Call(ctx, add_func, exports, 2, args);

// 处理返回值
if (!JS_IsException(call_result)) {
    int32_t res;
    if (JS_ToInt32(ctx, &res, call_result) == 0) {
        printf("add(5, 3) = %"PRIi32"\n", res); // 输出: add(5, 3) = 8
    }
} else {
    // 处理函数调用异常
    JSValue err = JS_GetException(ctx);
    char *err_str = JS_ToCString(ctx, err);
    fprintf(stderr, "函数调用失败: %s\n", err_str);
    JS_FreeCString(ctx, err_str);
    JS_FreeValue(ctx, err);
}

// 释放所有JSValue资源
JS_FreeValue(ctx, call_result);
JS_FreeValue(ctx, arg1);
JS_FreeValue(ctx, arg2);
JS_FreeValue(ctx, add_func);
JS_FreeValue(ctx, exports);
JS_FreeValue(ctx, module_result);

注意事项

  • 编译QuickJS时需确保启用模块支持(开启CONFIG_MODULE编译选项)。
  • 如果模块依赖NodeJS内置模块(如fs、path),需在QuickJS中实现对应的模块加载器,或用esbuild将所有依赖打包为单文件模块,避免外部依赖问题。
  • 对于复杂模块,需注意模块的依赖解析和加载顺序,QuickJS兼容ES模块规范,esbuild转换后的CommonJS模块可直接加载。

内容的提问来源于stack exchange,提问作者ijustlovemath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:35:20