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

能否通过QuickJS从C语言调用JS函数并存储返回值至C数组/结构体?

可以用QuickJS从C调用JS函数并转换返回值到C类型

当然可以。QuickJS提供了完整的C API,能够实现JS与C之间的类型互转,包括将JS数组、对象映射到C数组、结构体中。下面是针对你给出的JS函数的具体实现示例:

完整实现代码

#include "quickjs.h"
#include <stdio.h>
#include <string.h>

// 对应函数b返回对象的C结构体
typedef struct {
    char message[100];
} BResult;

int main() {
    // 初始化QuickJS运行时和上下文
    JSRuntime *rt = JS_NewRuntime();
    JSContext *ctx = JS_NewContext(rt);

    // 加载目标JS代码
    const char *js_code = 
        "function a(input){\n"
        "    return [input,input*2]\n"
        "}\n"
        "\n"
        "function b(input){\n"
        "   return {\n"
        "       message:`Hello, ${input}!`\n"
        "   }\n"
        "}";
    JSValue eval_result = JS_Eval(ctx, js_code, strlen(js_code), "test.js", JS_EVAL_TYPE_GLOBAL);
    if (JS_IsException(eval_result)) {
        JS_FreeValue(ctx, eval_result);
        JS_FreeContext(ctx);
        JS_FreeRuntime(rt);
        return 1;
    }
    JS_FreeValue(ctx, eval_result);

    // --- 调用函数a,将返回的JS数组转为C数组 ---
    JSValue fn_a = JS_GetPropertyStr(ctx, JS_GetGlobalObject(ctx), "a");
    if (JS_IsFunction(ctx, fn_a)) {
        JSValue args_a[] = {JS_NewInt32(ctx, 5)};
        JSValue arr_result = JS_Call(ctx, fn_a, JS_UNDEFINED, 1, args_a);
        
        if (JS_IsArray(ctx, arr_result)) {
            uint32_t arr_len = JS_GetArrayLength(ctx, arr_result);
            int c_arr[2] = {0};
            for (uint32_t i = 0; i < arr_len; i++) {
                JSValue elem = JS_GetPropertyUint32(ctx, arr_result, i);
                if (JS_IsInt32(elem)) {
                    c_arr[i] = JS_VALUE_GET_INT32(elem);
                }
                JS_FreeValue(ctx, elem);
            }
            printf("函数a返回的C数组:%d, %d\n", c_arr[0], c_arr[1]);
        }

        JS_FreeValue(ctx, arr_result);
        JS_FreeValue(ctx, args_a[0]);
    }
    JS_FreeValue(ctx, fn_a);

    // --- 调用函数b,将返回的JS对象转为C结构体 ---
    JSValue fn_b = JS_GetPropertyStr(ctx, JS_GetGlobalObject(ctx), "b");
    if (JS_IsFunction(ctx, fn_b)) {
        JSValue args_b[] = {JS_NewString(ctx, "World")};
        JSValue obj_result = JS_Call(ctx, fn_b, JS_UNDEFINED, 1, args_b);
        
        if (JS_IsObject(obj_result)) {
            BResult c_struct = {0};
            JSValue msg_val = JS_GetPropertyStr(ctx, obj_result, "message");
            if (JS_IsString(msg_val)) {
                const char *msg_str = JS_ToCString(ctx, msg_val);
                strncpy(c_struct.message, msg_str, sizeof(c_struct.message)-1);
                JS_FreeCString(ctx, msg_str);
            }
            JS_FreeValue(ctx, msg_val);
            printf("函数b返回的结构体内容:%s\n", c_struct.message);
        }

        JS_FreeValue(ctx, obj_result);
        JS_FreeValue(ctx, args_b[0]);
    }
    JS_FreeValue(ctx, fn_b);

    // 清理资源
    JS_FreeContext(ctx);
    JS_FreeRuntime(rt);
    return 0;
}

关键注意点

  • 内存管理:所有JSValue类型的变量使用完毕后必须用JS_FreeValue释放;通过JS_ToCString获取的C字符串需要用JS_FreeCString释放,避免内存泄漏。
  • 类型校验:转换前必须通过JS_IsArray、JS_IsFunction、JS_IsString等API检查JS值的类型,防止非法访问导致程序崩溃。
  • 动态结构处理:如果JS返回的数组/对象长度或结构不确定,需要使用动态内存分配(比如malloc)来存储C端数据,避免栈溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:45:39