use*_*901 30 javascript emscripten
我是Emscripten/javascript以及Overstack社区的新手.如果我的情况已经得到解决,我会事先道歉.
在Windows 7环境中,我使用emcc编译了一个简单的c程序,它接受一个数组并对其进行修改(见下文).
double* displayArray(double *doubleVector) {
for (int cnt = 0; cnt < 3; cnt++)
printf("doubleVector[%d] = %f\n", cnt, doubleVector[cnt]);
doubleVector[0] = 98;
doubleVector[1] = 99;
doubleVector[2] = 100;
for (int cnt1 = 0; cnt1 < 3; cnt1++)
printf("modified doubleVector[%d] = %f\n", cnt1, doubleVector[cnt1]);
return doubleVector;
}
int main() {
double d1, d2, d3;
double array1[3];
double *array2;
array1[0] = 1.00000;
array1[1] = 2.000000;
array1[2] = 3.000000;
array2 = displayArray(array1);
for (int cntr =0; cntr < 3; cntr++)
printf("array1[%d] = %f\n", cntr, array1[cntr]);
for (int cnt = 0; cnt < 3; cnt++)
printf("array2[%d] = %f\n", cnt, array2[cnt]);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
使用emcc的-o选项,我生成了一个.html文件,我加载到浏览器(Chrome).
python emcc displayArray7.c -o displayArray7.html -s EXPORTED_FUNCTIONS="['_main', '_displayArray'
Run Code Online (Sandbox Code Playgroud)
加载后,我看到在浏览器窗口中生成的输出符合预期(见下文).
doubleVector[0] = 1.000000
doubleVector[1] = 2.000000
doubleVector[2] = 3.000000
modified doubleVector[0] = 98.000000
modified doubleVector[1] = 99.000000
modified doubleVector[2] = 100.000000
array1[0] = 98.000000
array1[1] = 99.000000
array1[2] = 100.000000
array2[0] = 98.000000
array2[1] = 99.000000
array2[2] = 100.000000
Run Code Online (Sandbox Code Playgroud)
但是,当通过javascript控制台使用module.cwrap()命令并尝试直接调用函数(在main()之外)时,
> displayArray=Module.cwrap('displayArray', '[number]', ['[number]'])
> result = displayArray([1.0,2.0,3.0])
[1, 2, 3]
> result
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
我看到在浏览器中生成/显示以下内容,这不是我期望看到的.
doubleVector[0] = 0.000000
doubleVector[1] = 0.000000
doubleVector[2] = 0.000000
modified doubleVector[0] = 100.000000
modified doubleVector[1] = 100.000000
modified doubleVector[2] = 100.000000
Run Code Online (Sandbox Code Playgroud)
我有以下问题:
在调用Module.cwrap()时,我的返回类型和参数列表的语法是否正确?我在本教程的"与代码交互"部分中成功运行了int_sqrt()的简单直接示例,该部分处理将非指针变量传递给int_sqrt()例程.
当数组和/或指针传递给emscripten生成的javascript代码(或从中返回)时,是否会发生一些不同的事情?
当从main()调用时,函数浏览器中生成的输出displayArray()是如何工作的(如预期的那样); 但不是通过JavaScript控制台?
我是Emscripten/javascript的新手,所以任何信息/帮助将不胜感激.
谢谢,
FC
小智 35
Module.cwrap的预期格式允许'数组'被传递到函数中,但是如果你尝试返回一个数组,它会在结果上断言并失败
displayArrayA=Module.cwrap('displayArray','array',['array'])
displayArrayA([1,2,3])
// Assertion failed: ccallFunc, fromC assert(type != 'array')
Run Code Online (Sandbox Code Playgroud)
第二个限制是传入的数组应该是字节数组,这意味着您需要将任何传入的双数组转换为无符号的8位数字
displayArrayA=Module.cwrap('displayArray','number',['array'])
displayArrayA(new Uint8Array(new Float64Array([1,2,3]).buffer))
Run Code Online (Sandbox Code Playgroud)
以这种方式调用方法将调用您的函数,暂时将您的数组复制到Emscripten堆栈,该堆栈将在您调用的函数执行后重置,这使得返回的Array偏移可能因为释放堆栈空间而无法使用.
如果您想要函数的结果,更可取的是在Emscriptens堆系统中分配和保留数组.
Emscripten代码只能访问已在Emscripten的Heap空间中分配的内存.您尝试传递给函数的数组正在运行Emscripten代码的堆外部分配,并且与传入参数中预期的原始指针类型不匹配.
有几种方法可以访问数组以将数据传递给函数.所有这些都要求Emscripen知道你的内存在emscripten Module.HEAP*中的位置,所以最初的步骤是在某个时候调用Emscripten"_malloc"函数.
var offset = Module._malloc(24)
Run Code Online (Sandbox Code Playgroud)
这将允许您在3x 8字节双数组所需的Emscripten堆中分配所需的24个字节,并在Emscripten堆中返回Number偏移量,表示为阵列保留的U8 TypedArray偏移量.此偏移量是指针,当配置为使用原始指针偏移时,它将自动传递到cwrap displayArray函数中.
displayArray=Module.cwrap('displayArray','number',['number'])
Run Code Online (Sandbox Code Playgroud)
此时,如果您希望访问或修改数组的内容,只要malloc有效,您至少有以下选项:
使用临时包装的Float64阵列设置内存,除了以下两种访问方法外,没有简单的方法来恢复该值
Module.HEAPF64.set(new Float64Array([1,2,3]), offset/8);
displayArray(offset);
Run Code Online (Sandbox Code Playgroud)Module.setValue将使用'double'提示自动修改HEAPF64偏移量除以8.
Module.setValue(offset, 1, 'double')
Module.setValue(offset+8, 2, 'double')
Module.setValue(offset+16, 3, 'double')
displayArray(offset)
var result = [];
result[0] = Module.getValue(offset,'double'); //98
result[1] = Module.getValue(offset+8,'double') //99
result[2] = Module.getValue(offset+16,'double') //100
Run Code Online (Sandbox Code Playgroud)如果您希望在Javascript端更广泛地使用指针,可以手动从子HEAPF64条目中拉出子阵列TypedArray.这使您可以在完成功能后轻松读取值.这个TypedArray由与Emscripten的其余部分相同的堆支持,因此在Javascript端执行的所有更改都将反映在Emscripten端,反之亦然:
var doublePtr = Module.HEAPF64.subarray(offset/8, offset/8 + 3);
doublePtr[0] = 1;
doublePtr[1] = 2;
doublePtr[2] = 3;
// Although we have access directly to the HEAPF64 of the pointer,
// we still refer to it by the pointer's byte offset when calling the function
displayArray(offset);
//doublePtr[] now contains the 98,99,100 values
Run Code Online (Sandbox Code Playgroud)作为另一个答案的奖励,这里有一个用于分配float64数组的便利函数
function cArray(size) {
var offset = Module._malloc(size * 8);
Module.HEAPF64.set(new Float64Array(size), offset / 8);
return {
"data": Module.HEAPF64.subarray(offset / 8, offset / 8 + size),
"offset": offset
}
}
var myArray = cArray(3) // {data: Float64Array(3), offset: 5247688}
var displayArray = Module.cwrap('displayArray','number',['number'])
displayArray(myArray.offset)
Run Code Online (Sandbox Code Playgroud)
给出原始函数的输出:
doubleVector[0] = 98.000000
doubleVector[1] = 99.000000
doubleVector[2] = 100.000000
modified doubleVector[0] = 98.000000
doubleVector[1] = 99.000000
modified doubleVector[2] = 100.000000
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9293 次 |
| 最近记录: |