如何处理传递/返回emscripten编译代码的数组指针? [英] How to handle passing/returning array pointers to emscripten compiled code?

查看:203
本文介绍了如何处理传递/返回emscripten编译代码的数组指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Emscripten / javascript以及Overstack社区的新手。如果我的情况已经得到解决,我会事先道歉。

I am new to Emscripten/javascript as well as this Overstack community. I apologize, in advance, if my situation has already been addressed.

在Windows 7环境中,我使用emcc编译了一个简单的c程序,它接受一个数组并对其进行修改(见下文)。

From a windows 7 environment, I've used emcc to compile a simple c program which accepts an array and modifies it (see below).

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;
}

使用emcc的-o选项,我生成了一个.html文件,我加载到浏览器(Chrome)。

Using the -o options for emcc, I generated a .html file which I loaded to a browser (Chrome).

python emcc displayArray7.c -o displayArray7.html -s EXPORTED_FUNCTIONS="['_main', '_displayArray'

加载后,我看到在浏览器窗口中生成的输出符合预期(见下文)。

Upon loading, I see that the output being generated within the browser window is as expected (see below).

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

但是,当通过javascript控制台使用module.cwrap()命令并尝试直接调用函数(在main()之外)时,

However, when using the module.cwrap() command via javascript console and attempting to invoke the function directly (outside of main()) ,

> displayArray=Module.cwrap('displayArray', '[number]', ['[number]'])

> result = displayArray([1.0,2.0,3.0])
[1, 2, 3]
> result
[1, 2, 3]

我看到生成/显示以下内容在浏览器中,这不是我期望看到的。

I am seeing the following being generated/displayed in the browser which is NOT what I expect to see.

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   

我有以下问题:


  1. 我的语法是否正确在我调用Module.cwrap()时返回类型和参数列表是否正确?我已经在本教程的与代码交互部分中成功运行了int_sqrt()的简单,直接的示例,该部分处理将非指针变量传递给int_sqrt()例程。

  1. Do I have the syntax correct for the return type and parameter listing correct in my call to Module.cwrap()? I've successfully run the simple, straight-forward example of int_sqrt() in the "Interacting with code" section of the tutorial which deals with passing non-pointer variables to the int_sqrt() routine.

当数组和/或指针传递给emscripten生成的javascript代码(或从中返回)时,是否会发生不同的事情?

Is there something different that is happening when arrays and/or pointers are passed to (or returned from) the emscripten-generated javascript code?

当从main()调用时,函数浏览器中生成的输出displayArray()是如何工作的(如预期的那样);但不是通过javascript控制台?

How is that the generated output in the browser of the function, displayArray(), works (as expected) when called from main(); but not via the javascript console?

我是Emscripten / javascript的新手,所以任何信息/帮助将不胜感激。

I am new to Emscripten/javascript so any info/assistance will be greatly appreciated.

谢谢,

FC

推荐答案

Module.cwrap的预期格式允许'数组'被传递到函数中,但是如果你尝试返回一个数组,它将在结果上断言并失败

The expected format of Module.cwrap does allow for 'array's to be passed into the function, but will assert on result and fail if you attempt to return an array

displayArrayA=Module.cwrap('displayArray','array',['array'])
displayArrayA([1,2,3]) 
// Assertion failed: ccallFunc, fromC assert(type != 'array')

第二个限制是传入的数组应该是字节数组,这意味着你需要将任何传入的双数组转换为无符号的8位数字

A second restriction of this is that incoming arrays are expected to be byte arrays, meaning you would need to convert any incoming double arrays into unsigned 8-bit numbers

displayArrayA=Module.cwrap('displayArray','number',['array'])
displayArrayA(new Uint8Array(new Float64Array([1,2,3]).buffer))

以这种方式调用方法将调用您的函数,暂时将数组复制到Emscripten堆栈中l在调用函数执行后重置,使得返回的Array偏移可能因为释放堆栈空间而无法使用。

Calling the method this way will invoke your function, temporarily copying your arrays to the Emscripten stack which will be reset after your invoked function's execution, making the returned Array offset potentially unusable as it is freed stackspace.

如果你想得到你的结果,那就更好了函数,在Emscriptens堆系统中分配和保留数组。

It is much more preferable, if you want the results of your function, to allocate and preserve an array inside Emscriptens Heap system.

Emscripten代码只能访问已在Emscripten的堆空间中分配的内存。您尝试传递给函数的数组正在运行Emscripten代码的堆外部分配,并且与传入参数中预期的原始指针类型不匹配。

Emscripten code is only able to access memory that has been allocated within Emscripten's Heap space. The arrays that you are attempting to pass into the function are being allocated outside the heap that the Emscripten code is running against, and do not match the raw pointer type expected in the incoming arguments.

有几种方法可以访问数组以将数据传递给函数。所有这些都要求Emscripen知道你的内存在emscripten Module.HEAP *中的位置,所以最初的步骤是在某个时候调用Emscripten_malloc函数。

There are several ways that you can gain access to an array to pass data to your functions. All of these require Emscripen having knowledge of the location of your memory inside the emscripten Module.HEAP*, so the initial step is at some point to call the Emscripten "_malloc" function.

var offset = Module._malloc(24)

这将允许您在3x 8字节双数组所需的Emscripten堆中分配所需的24个字节,并在Emscripten堆中返回表示U8 TypedArray偏移的Number偏移量为您的阵列保留。这个偏移量是你的指针,当配置为使用原始指针偏移量时,它将自动传递到你的cwrap displayArray函数。

This would allow you to allocate the required 24 bytes in the Emscripten heap needed for your 3x 8-byte double array, and returns a Number offset in the Emscripten heap denoting the U8 TypedArray offset reserved for your array. This offset is your pointer, and will automatically work being passed into your cwrap displayArray function when it is configured to use the raw pointer offsets.

displayArray=Module.cwrap('displayArray','number',['number'])

此时,如果您希望访问或修改数组的内容,只要malloc有效,您至少有以下选项:

At this point, if you wish to access or modify the contents of the array, as long as the malloc is valid, you have at least the following options:


  1. 使用临时包装的Float64数组设置内存,除了以下两种访问方法外,没有简单的方法来恢复该值

  1. Set the memory using a temporarily wrapped Float64 array, with no easy way to recover the value except the following 2 methods of access

Module.HEAPF64.set(new Float64Array([1,2,3]), offset/8);
displayArray(offset);


  • Module.setValue将使用'double'提示自动修改HEAPF64偏移量,划分8。

  • Module.setValue will use the 'double' hint to automatically modify the HEAPF64 offset, divided by 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
    


  • 如果你想在Javascript端更广泛地使用你的指针,你可以拉手动关闭HEAPF64条目的子阵列TypedArray。这使您可以在完成功能后轻松读取值。这个TypedArray由与Emscripten的其余部分相同的堆支持,因此在Javascript端执行的所有更改都将反映在Emscripten端,反之亦然:

  • If you wish to use your pointer more extensively on the Javascript side, you can pull a subarray TypedArray off the HEAPF64 entry manually. This allows you to easily read the values once you have finished executing your function. This TypedArray is backed by the same heap as the rest of the Emscripten, so all changes performed on the Javascript side will be reflected on the Emscripten side and vice-versa:

    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
    


  • 这篇关于如何处理传递/返回emscripten编译代码的数组指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆