gpt4 book ai didi

javascript - 使用 Emscripten 将 JavaScript 字符串数组传递给 C 函数

转载 作者:行者123 更新时间:2023-12-05 00:25:10 26 4
gpt4 key购买 nike

我是 WebAssembly 和 Emscripten 的新手,我正在尝试将 JavaScript 中的字符串数组传递给 C 函数,以便使用 Module.cwrap(...) 进行进一步处理.理想情况下,我还想从 C 将字符串数组返回给 JavaScript。

下面是我正在寻找的一些伪代码:

JS

const strings = ["foo", "bar", "fool", "gnar"]
const result = Module.cwrap("myCFunc", "array", ["array"])
console.log(result) // ["my", "transformed", "array"]

C
char **myCFunc(char **input) {
// do some processing. Specifically some md5 hashing...
return output;
}

我的猜测是我不能自己将多维数组从 JS 传递给 C 函数,而是必须使用 WebAssembly 堆内存。
我知道 emscripten JS API支持这种东西,但我已经很久没有写过 C 语言了,这种类型的指针操作的细节目前超出了我的范围。

最佳答案

这里有两个问题:一个是如何将数据数组传递给 C 函数,另一个是如何从 C 函数中获取数据数组。
对于第一个问题,您需要将每个 JS 字符串转换为 C 字符串,为包含每个此类 C 字符串的数组分配 C 内存,并将值写入数组 - 然后您可以将其传递给您的函数。
例如:
emcc 标志:

-s EXPORTED_FUNCTIONS="['UTF8ToString','stringToUTF8Array','lengthBytesUTF8']"

-s EXTRA_EXPORTED_RUNTIME_METHODS="['_free','_malloc','setValue']"
Javascript:
// convert a Javascript string to a C string
function str2C(s) {
var size = lengthBytesUTF8(s) + 1;
var ret = _malloc(size);
stringToUTF8Array(s, HEAP8, ret, size);
return ret;
}

function run_with_strings(strings) {
let c_strings = strings.map(x => str2C(x));


// allocate and populate the array. adapted from https://stackoverflow.com/a/23917034
let c_arr = _malloc(c_strings.length*4); // 4-bytes per pointer
c_strings.forEach(function(x, i) {
Module.setValue(argsC + i * 4, x, "i32");
});

// invoke our C function
let rc = myCFunc(c_strings.length, c_arr);

// free c_strings
for(let i = 0; i < c_strings.length; i++)
_free(c_strings[i]);

// free c_arr
_free(c_arr);

// return
return rc;
}
对于第二个问题,您的 C 函数可能难以使用,因为它不返回项目数(尽管我认为您可以推断出最后一项是否为 NULL 并且没有其他项为 NULL)。一种解决方案是让您的函数返回一个不透明的指针,然后可以将其反馈到一些辅助函数中,例如:
在 C 中:
struct myCFuncReturnValue {
char **values;
unsigned int count;
};

struct myCFuncReturnValue *myCFunc(char **input) {
struct myCFuncReturnValue *p = calloc(1, sizeof(*p));
...
p->count = ...;
p->values = ...;
return p;
}

char *myCFunc_value(struct myCFuncReturnValue *p, unsigned int i) {
return i < p->count ? p->values[i] : NULL;
}

unsigned int myCFunc_count(struct myCFuncReturnValue *p) {
return p->count;
}

void myCFunc_destroy(struct myCFuncReturnValue *p) {
// maybe here you need to free each p->values[i];
free(p->values);
free(p);
}
Javascript:
// continuing with the rc value from run_with_strings():

for(let i = 0, j = myCFunc_count(rc); i < j; i++) {
let c_string = myCFunc_value(rc, i);
console.log(UTF8ToString(c_string));
}

myCFunc_destroy(rc);

关于javascript - 使用 Emscripten 将 JavaScript 字符串数组传递给 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46750777/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com