通过 Emscripten 在 Javascript 中进行结构操作

Posted

技术标签:

【中文标题】通过 Emscripten 在 Javascript 中进行结构操作【英文标题】:Struct operations in Javascript through Emscripten 【发布时间】:2015-03-06 17:27:43 【问题描述】:

我在 emscripten 在 C 和 javascript 之间进行互操作时遇到了很多问题。

更具体地说,鉴于指向该结构的指针作为 external library 传递到 javascript,我无法访问在 javascript 中用 C 语言创建的结构。

看看下面的代码:

C:

#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>

struct test_st;

extern void read_struct(struct test_st *mys, int siz);

struct test_st
    uint32_t my_number;
    uint8_t my_char_array[32];
;

int main()
    struct test_st *teststr = malloc(sizeof(struct test_st));
    teststr->my_number = 500;
    for(int i = 0; i < 32; i++)
        teststr->my_char_array[i] = 120 + i;
    
    for(int i = 0; i < 32; i++)
        printf("%d\n",teststr->my_char_array[i]);
    
    read_struct(teststr,sizeof(teststr));
    return 0;

Javascript:

mergeInto(LibraryManager.library,
    
        read_struct: function(mys,siz)
            var read_ptr = 0;
            console.log("my_number: " + getValue(mys + read_ptr, 'i32'));
            read_ptr += 4;
            for(var i = 0; i < 32; i++)
                console.log("my_char[" + i + "]: " + getValue(mys + read_ptr, 'i8'));
                read_ptr += 1;
            ;
        ,
    );

然后使用emcc cfile.c --js-library jsfile.js 编译。

这里的问题是你不能真正在javascript中读取结构,你必须根据结构字段的大小从各自的地址获取内存(所以从uint32_t读取4个字节,从uint8_t读取1个字节) .好的,这不是问题,除了您还必须声明 getValue 工作的 LLVM IR 类型,并且它不包括无符号类型,因此对于数组,它将达到 127 和溢出到 -128,当预期的行为是继续上升时,因为变量是无符号的。

我到处寻找答案,但显然这种特定的预期行为并不常见。在我应用它的程序中更改结构是不可能的(不是上面的示例)。

【问题讨论】:

【参考方案1】:

一种方法是使用 Emscripten 公开的 HEAP* 类型数组,它们确实有未签名的视图:

mergeInto(LibraryManager.library, 
  read_struct: function(myStructPointer, size) 
    // Assumes the struct starts on a 4-byte boundary
    var myNumber = HEAPU32[myStructPointer/4];
    console.log(myNumber);
    // Assumes my_char_array is immediately after my_number with no padding
    var myCharArray = HEAPU8.subarray(myStructPointer+4, myStructPointer+4+32);
    console.log(myCharArray);
  
);

这在我的测试中有效,运行 Emscripten 1.29.0-64 位,但如前所述,它对对齐/填充做出了假设。我测试的案例似乎表明结构似乎总是从 4 字节边界开始,并且结构内的 32 位无符号整数也总是在 4 字节边界上对齐,因此可以被 HEAPU32 访问。

但是,我不知道您是否可以依赖 Emscripten 中的这种行为。我的理解是你不能在通常的 C/C++ 世界中。

【讨论】:

谢谢!只是给其他人的便条(这让我有点困惑)。 HEAPU8.subarray 接受 startend 而不是 startlength

以上是关于通过 Emscripten 在 Javascript 中进行结构操作的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Emscripten 激活抗锯齿

在 html5 画布上通过 emscripten 使用 WebGL

如何通过 emscripten 在 C++ 和 javascript 之间传递字符串

在 OS X 上安装 Emscripten

将文件名传递给 Emscripten 生成的 js 作为参数

快速上手 WebAssembly 应用开发:Emscripten 使用入门