如何通过WebIDL及WebIDL绑定器实现JavaScript向C++按引用传递数组
如何通过WebIDL及WebIDL绑定器实现JavaScript向C++按引用传递数组
你想要的效果是让JavaScript数组传给C处理后,原数组直接被修改,不用额外做拷贝操作对吧?用sequence<float>确实达不到这个目的——按照WebIDL的规范,sequence<T>是按值传递的,JS数组会被拷贝一份到C的内存里,你在C++里修改的只是这份拷贝,原JS数组不会有任何变化。
下面给你讲符合预期的实现方式:
正确的WebIDL写法
我们需要把参数类型从sequence<float>换成Float32Array,这是WebIDL里对应JS类型化数组的接口,它可以直接映射到底层的连续内存,实现类似“引用传递”的效果:
// interface.idl interface Foo { void Foo(); void process_array(Float32Array array, long num_frames); };
C++端实现
C++的头文件和实现可以保持你原来的逻辑,参数用float*或者float[]都可以(因为Float32Array的底层就是连续的float内存块):
// main.hpp struct Foo { Foo(); void process_array(float* array, int num_frames); };
// 实现文件 void Foo::process_array(float array[], int num_frames) { for (int i = 0; i < num_frames; i++) { array[i] *= 0.5; } }
JavaScript调用
调用的时候直接传入Float32Array类型的数组(如果想用普通JS数组,可以手动转成TypedArray,多数绑定器也支持自动转换):
// 直接使用Float32Array const arr = new Float32Array([1, 2, 3]); foo.process_array(arr, arr.length); console.debug(arr); // 输出: Float32Array(3) [0.5, 1, 1.5] // 如果你习惯用普通JS数组,可以先转换 const normalArr = [1, 2, 3]; const typedArr = new Float32Array(normalArr); foo.process_array(typedArr, typedArr.length); console.debug(Array.from(typedArr)); // 输出: [0.5, 1, 1.5]
为什么这样可行?
WebIDL里的Float32Array对应JS的类型化数组,它的底层是一块连续的内存区域。WebIDL绑定器会直接把这块内存的指针传递给C++,而不是做数组拷贝。所以你在C++里修改这个指针指向的内存时,JS里的原Float32Array会实时同步这些变化,完美实现你想要的“按引用传递”效果。
另外你提到的frozen array确实只能用作对象的属性,不能作为方法参数,所以不适合这个场景。如果用你之前想的“把结果存到对象属性再读回来”的方式,不仅多了额外的拷贝步骤,代码也更繁琐,完全没必要。
备注:内容来源于stack exchange,提问作者Nearoo
相关产品推荐
相关产品推荐

