我无法将双数组移交给通过 emscripten 生成的 WASM 文件。我已将其生成为 WASM=1 的 .js 输出文件,因此我还有一个 wasm 文件。
这是我的缩写 C++ 代码:
#include <iostream>
using namespace std;
extern "C" {
int main(int argc, char** argv) {
return 0;
}
double *calculate(double *x, double *y, int array_length) {
std:cout << "Array Length: " << array_length << endl;
for (int i = 0; i < array_length; i++) {
std::cout << "Coords: " << x[i] << ", " << y[i] << endl;
}
return new double[7]{1,1,2,3,5,8,13};
}
}
它在浏览器控制台中生成以下输出:
Array Length: 4 average.js:8:16057
Coords: 2.36377e+232, 2.36377e+232 average.js:8:16057
Coords: 5.9419e-310, 5.9419e-310 average.js:8:16057
Coords: 4.28375e-319, 4.28375e-319 average.js:8:16057
Coords: 1.4854e-313, 1.4854e-313
我可以看到它做了一些事情。
这是调用它的代码:
import { CalculationAdapterInterface, Coords, GraphData } from "../CalculationAdapterInterface";
import averageModule from "./average"
export default class CalculationWasmAdapter implements CalculationAdapterInterface {
async calculate(data: GraphData): Promise<Coords|void> {
const x = [ 5.0, 3.0, 2.0, 5.0];
const y = x.map(x => x/2);
const to_byte = (arr: number[]) => { return new Float64Array(arr).buffer}
const filePath = window.location.origin + "/average.wasm";
averageModule({locateFile: () => filePath}).then((module: any) => {
const calculate = module.cwrap('calculate', 'number', ['array', 'array', 'int'])
calculate(to_byte(x), to_byte(y), x.length);
})
}
}
我不明白为什么会在浏览器中生成输出。 当我更改数组中的输入值时,它不会更改打印值(打印的数量除外)。我强烈怀疑 C++ 代码不接收数组并从某些默认分配的空间读取。但为什么呢?
我只做过一次,我并不声称自己是专家,但我使用这种技术成功地将双精度数组从 JavaScript 传递到 C++。
我的理解是,如果你想从 JavaScript 访问内存,你必须意识到 JavaScript 和 WebAssembly 具有不同的内存布局。您可以使用 HEAPF64.set
将数据从 JavaScript 数组(具有自己的内存布局)复制到 Emscripten HEAP,WebAssembly 模块可以在其中访问数据。这是我的示例,它是node.js(抱歉,这就是我使用它的方式),但在浏览器平台中应该可以实现类似的操作。
const factory = require('./src/passarray.js');
factory().then(instance => {
const doubleArray = new Float64Array([1.0, 2.0, 3.0, 4.0, 5.0]);
const arrayPointer = instance._malloc(doubleArray.length * doubleArray.BYTES_PER_ELEMENT);
instance.HEAPF64.set(doubleArray, arrayPointer / doubleArray.BYTES_PER_ELEMENT);
instance._exampleFunction(arrayPointer);
instance._free(arrayPointer);
});
在C++方面:
extern "C" {
EMSCRIPTEN_KEEPALIVE
void exampleFunction(double* elems) {
// [your code here]
}
}