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

Posted

技术标签:

【中文标题】如何通过 emscripten 在 C++ 和 javascript 之间传递字符串【英文标题】:How to pass strings between C++ and javascript via emscripten 【发布时间】:2014-02-16 21:33:13 【问题描述】:

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

例如,我想写一个字符串长度函数。在 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++ 之间编组字符串类型?

【问题讨论】:

【参考方案1】:

extern "C" 无法识别 std::string。

您可能想试试这个: 测试.cpp

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

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

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

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

示例测试代码: 测试.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>

【讨论】:

这并没有回答完整的问题,即如何在 C++ 代码之间传递字符串。【参考方案2】:

如果对函数使用 extern "C",则不能在其签名中使用 C++ 类型。

所以如果你想使用std::string,那么你可以使用“Embind”或“WebIDL Binder”。参考here

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

P.S 我不知道如何在这里通过引用传递变量,所以按值传递。

// 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);

确保你通过了标志

--绑定

调用 emcc 时。

有another approach,您可以在其中从 JS 在 C++ 堆上执行 Malloc,然后进行操作,但上述方法应该更容易。

【讨论】:

"如果你在函数中使用 extern "C",你不能在它的签名中使用 C++ 类型。"我看到两个答案都声称这一点,但我认为这不是真的。 AFAIK 这只是防止名称修改的链接规范。我可以编译extern "C" void foo(std::string s) std::cout &lt;&lt; "hello, world" &lt;&lt; std::endl; 就好了【参考方案3】:

一些想法:

    我调用方法的唯一方法是使用crwapccall?var length = Module.ccall('stringLen', ['string'], 'number'); 您是否在EXPORTED_FUNCTIONS 参数中包含stringLenstringTestemcc 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/

希望对您有所帮助。

【讨论】:

以上是关于如何通过 emscripten 在 C++ 和 javascript 之间传递字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Socket.io 和 emscripten 使用 javascript 库?

使用 emscripten 将 c++ 代码编译为 javascript 以求两个数之和。练习

Emscripten 网页js调用C++ (ffmpeg)

Emscripten 网页js调用C++ (ffmpeg)

Emscripten 网页js调用C++ (ffmpeg)

如何使用 Emscripten 将对象从 Javascript 传递到 C++