能否通过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
相关产品推荐
相关产品推荐

