繁体   English   中英

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

[英]How to pass strings between C++ and javascript via emscripten

我正在学习 emscripten,在 C++ 和 JS 之间传递字符串时,我什至无法进行最基本的字符串操作。

比如我想写一个字符串长度function。 在 C++ 中:

extern "C" int stringLen(std::string p)
{
    return p.length();
}

从 javascript 调用为:

var len = _stringLen("hi.");

这对我来说是0 我如何使这项工作按预期进行? 我应该在这里使用哪种字符串类型? char const* ? std::wstring std::string 似乎没有一个工作; 我总是得到相当随机的值。

这只是开始......然后我如何从 C++ 像这样返回一个字符串?

extern "C" char *stringTest()
{
    return "...";
}

在 JS 中:

var str = _stringTest();

再一次,我无法找到一种方法来完成这项工作。 我总是在 JS 中得到垃圾。

所以我的问题很清楚:如何通过 Emscripten 在 JS 和 C++ 之间编组字符串类型?

extern“C”无法识别std :: string。

你可能想试试这个:
TEST.CPP

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

extern "C" int stringLen(char* p)
        {
            return strlen(p);
        }

使用以下命令编译cpp代码:

emcc Test.cpp -s EXPORTED_FUNCTIONS="['_stringLen']

示例测试代码:
的test.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Hello World !</title>
        <script src="a.out.js"></script>
        <script>
             var strLenFunction =  Module.cwrap('stringLen', 'number', ['string']);
             var len1 = strLenFunction("hi.");  // alerts 3
             alert(len1);
             var len2 = strLenFunction("Hello World"); // alerts 11
             alert(len2);
        </script>
    </head>
</html>

如果将extern“C”与函数一起使用,则不能在其签名中使用C ++类型。

因此,如果您想使用std :: string,则可以使用“Embind”或“WebIDL Binder”。 请参考这里

我更喜欢embind,所以这是你的问题的示例代码。

PS我不知道如何通过引用传递变量,所以按值进行。

// This is your routine C++ code
size_t MyStrLen(std::string inStr) {
    return inStr.length();
}

// This is the extra code you need to write to expose your function to JS
EMSCRIPTEN_BINDINGS(my_module) {
    function("MyStrLen", &MyStrLen);
}

现在在JS中你需要做的就是:

var myStr = "TestString";
Module.MyStrLen(myStr);

确保你通过旗帜

--bind

在调用emcc时。

还有另一种方法 ,你可以从JS在C ++堆上执行Malloc然后进行操作,但上述方法应该更容易。

一些想法:

  1. 我调用方法的唯一方法是使用crwapccall
    var length = Module.ccall('stringLen', ['string'], 'number');
  2. 您是否在EXPORTED_FUNCTIONS参数中包含stringLenstringTest
    emcc hello_world.cpp ... -s EXPORTED_FUNCTIONS=['_stringLen','_stringTest']

看看这里了解更多细节:
http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html

或者我的hello_world教程:
http://www.brightdigit.com/hello-emscripten/

希望这会有所帮助。

我来到这里寻找一种将字符串从 C/C++ 传递到 javascript 的方法。 这么多年后我发布答案的原因是我在这里或其他任何地方都找不到该问题的答案,所以我希望这可以帮助那些有类似问题的人。

emscripten 文档说明了以下关于可以使用cwrap / ccall ( emscripten docs ) 传递给 C/C++ 函数的类型:

The types are "number" (for a JavaScript number corresponding to a C integer, float, or general pointer), "string" (for a JavaScript string that corresponds to a C char* that represents a string) or "array" (for JavaScript 数组或对应于 C 数组的类型化数组;对于类型化 arrays,它必须是 Uint8Array 或 Int8Array)。

As the other answers have pointed out, you need to write the C function using a C string as the argument because that is the emscripten API (not because of extern "C" ).

如果你想返回一个字符串,你可能认为你可以只传递一个 C 字符串(有效地通过引用,因为它是指针)并修改该字符串:

// C function
extern "C" {
  void stringTest(char* output) {
    output[0] = 'H';
    output[1] = 'i';
  }
}

// Call to C function in javascript that does not modify output
let stringTestFunction =  Module.cwrap('stringTest', null, ['string']);
let output = "12"; // Allocate enough memory
stringTestFunction(output);
console.log(output); // 12

但是,这不起作用,因为在传递给 function 时会创建一个副本。 因此,您需要显式分配 memory 并传递一个指针。 Emscripten 为此提供了allocateUTF8UTF8ToString函数:

let stringTestFunction =  Module.cwrap('stringTest', null, ['number']); // the argument is 'number' because we will pass a pointer 
let output = "12";
let ptr = Module.allocateUTF8(output); // allocate memory available to the emscripten runtime and create a pointer
stringTestFunction(ptr);
output = Module.UTF8ToString(ptr); // read from the allocated memory to the javascript string
Module._free(ptr); // release the allocated memory
console.log(output); // Hi

因为我们正在将字符串转换为字符指针,所以我们也可以直接调用 function 而不使用cwrapemscripten 文档): Module._stringTest(ptr) 它需要一些额外的步骤,但现在您已将字符串从 C 传递到 javascript。

要使此示例正常工作,您可能需要使用以下标志进行编译: -sEXPORTED_FUNCTIONS="['_stringTest','_malloc','_free']"-sEXPORTED_RUNTIME_METHODS="['cwrap','allocateUTF8','UTF8ToString']"

还有更通用的方法可以为其他类型的 arrays 分配 memory( https://stackoverflow.com/a/23917034/12 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM