有没有更有效的方法将数组从C ++返回到javascript? [英] Is there a more efficient way to return arrays from C++ to javascript?

查看:99
本文介绍了有没有更有效的方法将数组从C ++返回到javascript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要将键入的数组从脚本化的C ++传递给javascript,我想出了这段代码

To pass typed array from emscripten'ed C++ to javascript I came up with this code

#include <emscripten/bind.h>
#include <emscripten/val.h>

auto test(const emscripten::val &input) {
  const auto data = emscripten::convertJSArrayToNumberVector<float>(input); // copies data

  // generate output in some form
  std::vector<float> output = { 1, 2, 3 };
  // make a typed array view of the output
  emscripten::val view{ emscripten::typed_memory_view(output.size(), output.data()) };
  // create new typed array to return
  auto result = emscripten::val::global("Float32Array").new_(output.size());
  // copy data from generated output to return object
  result.call<void>("set", view);

  return result;
}

EMSCRIPTEN_BINDINGS(KissFft) {
  emscripten::function("test", &test);
}

(使用 em ++ test.cpp -o test.html --bind 构建)

在这种情况下,有两个额外的副本:

In this case there are two extra copies:

    据我所知,从输入数组到wasm内存的拷贝是不可避免的.
  • the copy from input array to wasm memory, as far as I understand it's unavoidable;
const auto data = emscripten::convertJSArrayToNumberVector<float>(input);

  • 从wasm内存到javascript对象的副本:

  • the copy from wasm memory to javascript object:

    emscripten::val view{ emscripten::typed_memory_view(output.size(), output.data()) };
    auto result = emscripten::val::global("Float32Array").new_(output.size());
    result.call<void>("set", view);
    
    return result;
    

  • 是否有一种方法可以避免在第二种情况下从生成的输出到javascript对象的多余副本?

    我知道有可能返回这样的内存视图:

    I'm aware of the possibility to return memory view like this:

    std::vector<float> output;
    
    auto test(const emscripten::val &input) {
      const auto data = emscripten::convertJSArrayToNumberVector<float>(input);
    
      //generate output
      return emscripten::val{ emscripten::typed_memory_view(output.size(), output.data()) };
    }
    
    EMSCRIPTEN_BINDINGS(KissFft) {
      emscripten::function("test", &test);
    }
    

    但是在这种情况下,返回的对象引用了 output 静态对象所拥有的基础内存,从而产生了所有后果,例如在C ++端修改内存,甚至取消分配内存.

    But in this case the returned object refers to the underlying memory owned by output static object with all the consequences, like modifying the memory on the C++ side, or even deallocating it.

    推荐答案

    我当时想降低一点.在此处(而不是注释)粘贴代码片段(摘录自emscripten的embind示例,在C中,但您可以对C ++进行相同操作.)

    I was thinking to go lower a bit. Putting here (instead of comment) to paste snippets (taken from embind examples from emscripten, here in C but you may do the same with C++).

    // quick_example.cpp
    #include <emscripten/bind.h>
    #include <stdio.h>
    
    using namespace emscripten;
    
    struct buffer {
      unsigned int pointer;
      unsigned int size;
    };
    
    buffer lerp() {
        buffer myBuffer;
        unsigned int size = 10;
    
        float * myTab = (float*)malloc(size * sizeof(float));
    
        for (int i = 0; i < size; i++) {
          myTab[i] = 2.5 * i;
          printf(" Native side index: %d value: %f address: %p\n", i, myTab[i], &myTab[i]);
        }
    
        myBuffer.pointer = (unsigned int) myTab; 
        myBuffer.size = size;
    
        printf(" Native side pointer: %p size: %d\n", myTab, size);
        return myBuffer;
    }
    
    EMSCRIPTEN_BINDINGS(my_module) {
        value_array<buffer>("buffer")
            .element(&buffer::pointer)
            .element(&buffer::size)
            ;
    
        function("lerp", &lerp);
    }
    

    index.html-您可以在js中复制,查看并最终释放内存什么(据我了解,这是上面的问题之一?)

    index.html - here in js you may copy, make a view and finally free the memory what (as I understood was one of the problems from above?)

       <!doctype html>
        <html>
          <script>
            var Module = {
              onRuntimeInitialized: function() {
                var result =  Module.lerp();
                console.log(" JS side pointer: " + result[0] + " size: " + result[1]);
         
                for (var i = 0; i < result[1]; i++) {
                  console.log("index: " + i + " value: " + Module.HEAPF32[(result[0] + i * 4) / 4] + " pointerInc: " + (result[0] + i * 4));
                }
        
                Module._free(result[0]);
              }
            };
          </script>
          <script src="lerp.js"></script>
        </html>
    

    构建命令

    emcc --bind -o lerp.js lerp.cpp
    

    这篇关于有没有更有效的方法将数组从C ++返回到javascript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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