NSDT工具推荐Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割

本文介绍在 WASM 中编译 C 库后,如何访问 C 中定义的结构。

当在 Javascript 中使用时,我没有找到任何直接从 WASM 访问结构的方法。 Emscripten 提供了一个选项 embind,它将 C++ 函数和类绑定到 Javascript,但不适用于 C。

我在互联网上搜索了其他开发人员如何解决此类问题,我发现了一些有趣的方法来直接使用 WASM 内存并在 C 和 Javascript 之间映射值。 但是对于 WASM 初学者来说,我发现它有点难以理解。 他们首先要了解 WASM 的内存系统。

我认为首先要鼓励初学者用简单的语言展示它是如何工作的,然后当他对它感到满意或有任何严重的问题或兴趣时,再深入挖掘其中的细节。

为了牢记这一点,我写了这篇文章。 让我们开始吧

首先在C中,定义一个struct,导出相关的函数,包括create、destroy和需要的getter/setter函数:

#include <emscripten.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct _WA_STRUCT {
 int a;
 double pi;
}WA_STRUCT;
void EMSCRIPTEN_KEEPALIVE structCreate(WA_STRUCT **ppStruct) {
    WA_STRUCT   *pStruct = malloc(sizeof(WA_STRUCT));
    
    pStruct->a = 35;
    pStruct->b = 3.14;
*ppStruct  = pStruct;
}
void EMSCRIPTEN_KEEPALIVE structDestory(WA_STRUCT *pStruct) {
    free(pStruct);
}
void EMSCRIPTEN_KEEPALIVE structPrint(WA_STRUCT *pStruct) {
    printf("Struct Values {%d, %.3f}\n", pStruct->a, pStruct->b);
}
void EMSCRIPTEN_KEEPALIVE structQuery(WA_STRUCT *pStruct, int *pa, double *pb) {
    *pa = pStruct->a;
    *pb = pStruct->b;
}
void EMSCRIPTEN_KEEPALIVE structSet(WA_STRUCT *pStruct, int a, double b) {
    pStruct->a = a;
    pStruct->b = b;
}

导出所需C函数的方法有多种。 我使用 EMSCRIPTEN_KEEPALIVE 预处理器导出了函数。 现在只需使用 emscripten 编译器编译这段代码:

emcc test.c -o test.js -s "EXTRA_EXPORTED_RUNTIME_METHODS=['getValue', 'setValue']"

有趣的是如何在 Javascript 中使用导出的函数。 我更愿意将全部责任交给 C 来处理对象及其生命周期,在 Javascript 方面,只是尽量使代码尽可能简单。

这里唯一重要的是要了解 WASM 中没有任何指针概念,一切都在 WASM 堆栈或堆中,因此要获取新创建的结构的地址,首先分配 4 个字节的内存来存储指针,然后获取 所需的信息。 请看下面的代码。 为了在 Javascript 中测试 WASM,我喜欢使用 node.js 环境而不是 web,但这取决于你,你可以使用 web。

const Module = require('./test.js')
Module['onRuntimeInitialized'] = function() {
   // create a var containing the address of struct
    var ppStruct = Module._malloc(4);
   
   // Create a struct 
   Module._structCreate(ppStruct);
   // Get the actual location of the object
   var pStruct = Module.getValue(ppStruct, "i32");
   Module._structPrint(pStruct); // print default values
   // To query the values from struct, again created two more pointers pa & pb
   var pa = Module._malloc(4);
   var pb = Module._malloc(4);

   Module._structQuery(pStruct, pa, pb); // query values
   var a = Module.getValue(pa, "i32");    // ask for 4 byte int value
   var b = Module.getValue(pb, "double"); // ask for double
   console.log("Queried values {" + a + ", "+ b + "}");
   // set new value
   Module._structSet(pStruct, 10, 7.25);
   Module._structPrint(pStruct);
    
   // Cleanup
   Module._structDestory(pStruct);
   Module._free(pa);
   Module._free(pb);
   Module._free(ppStruct);
}

用 Node.js 运行该文件:

node example.js

输出如下:

Struct Values {35, 3.140}
Queried values {35, 3.14}
Struct Values {10, 7.250}

我以非常简单的方式编写代码来解释如何以简单的方式处理 C 结构。 如果你是一位经验丰富的开发人员,当然可以使用自己的方式来绑定 C 结构和 JavaScript 对象。


原文链接:Webassembly & C struct

BimAnt翻译整理,转载请标明出处