nodejs如何将变量传递给c方法char *

时间:2018-05-06 09:04:43

标签: c node.js emscripten

这样的代码
int stringlen(char* p){
   return strlen(p);
}

使用emcc -s EXPORTED_FUNCTIONS =“['_ stringlen']”example.c -o example.js

并在nodejs中调用em_module1._stringlen('sadfsa'),为什么返回4 ..... 我如何从nodejs传递c类型char *?

1 个答案:

答案 0 :(得分:1)

说明

内部具有功能_stringlen()的已编译WebAssembly模块使用其内存表示为linear memory。编译后的函数仅知道其模块的内存。因此,指针char*必须指向模块内存的一块。

快速解决方案

除了添加缺少的内容,我们将保持C代码不变:

#include <string.h>

int stringlen(char *p)
{
   return strlen(p);
};

输出的JavaScript代码example.js包含用于内存管理等功能。接下来,在test.js脚本中,我们:

  1. 将我们的字符串转换为原始字节(转换为UInt8Array
  2. 为该字符串分配模块内存的一部分(结尾不需要\0字符)
  3. (a)访问模块内存中分配的块,并(b)用我们的原始字符串填充它(我们访问内存是因为它代表单个无符号字节HEAPU8
  4. 释放分配的块
const Module = require('./example.js');

const str_raw = new TextEncoder().encode('Lorem ipsum'); // 1)
let ptr = Module._malloc(str_raw.length); // 2)
let chunk = Module.HEAPU8.subarray(ptr, ptr + str_raw.length); // 3A)
chunk.set(str_raw); // 3B)

console.log(Module._stringlen(chunk.byteOffset));
Module._free(ptr); // 4)

对于编译,我已强制对WebAssembly模块(-s WASM_ASYNC_COMPILATION=0)进行同步编译,以确保在require()之后该模块将准备就绪:

emcc -s EXPORTED_FUNCTIONS="['_stringlen']" example.c -o example.js -s WASM_ASYNC_COMPILATION=0

我们按照node test.js执行脚本。

其他解决方案

我最喜欢的解决方案是已经提到的embind。它要求您使用C ++:

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

size_t stringlen(std::string p)
{
   return p.size();
};

EMSCRIPTEN_BINDINGS(Module)
{
   emscripten::function("stringlen", &stringlen);
}

我们通过使用带有--bind标志的 embind 来编译代码:

emcc example.cpp -o example.js -s WASM_ASYNC_COMPILATION=0 -std=c++11 --bind

现在,函数调用更加简单:

const Module = require('./example.js');

console.log(Module.stringlen('Lorem ipsum'))