ten*_*our 6 javascript c++ emscripten
我正在学习emscripten,在C++和JS之间传递字符串时,我甚至无法获得最基本的字符串操作.
例如,我想写一个字符串长度函数.在C++中:
extern "C" int stringLen(std::string p)
{
return p.length();
}
Run Code Online (Sandbox Code Playgroud)
从javascript调用:
var len = _stringLen("hi.");
Run Code Online (Sandbox Code Playgroud)
这0让我感到满意.如何按预期工作?我应该在这里使用哪种字符串类型?char const*?std::wstring?std::string?似乎没有工作; 我总是得到相当随机的价值观.
这只是一个开始......我如何从这样的C++ 返回一个字符串?
extern "C" char *stringTest()
{
return "...";
}
Run Code Online (Sandbox Code Playgroud)
在JS中:
var str = _stringTest();
Run Code Online (Sandbox Code Playgroud)
再说一遍,我找不到办法让这项工作; 我总是在JS中得到垃圾.
所以我的问题很清楚:我如何通过Emscripten编组JS和C++之间的字符串类型?
Fac*_*alm 10
extern"C"无法识别std :: string.
您可能想尝试这个:
Test.cpp
#include <emscripten.h>
#include <string.h>
extern "C" int stringLen(char* p)
{
return strlen(p);
}
Run Code Online (Sandbox Code Playgroud)
使用以下命令编译cpp代码:
emcc Test.cpp -s EXPORTED_FUNCTIONS="['_stringLen']
Run Code Online (Sandbox Code Playgroud)
示例测试代码:
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>
Run Code Online (Sandbox Code Playgroud)
如果将 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);
}
Run Code Online (Sandbox Code Playgroud)
现在在 JS 中你需要做的就是:
var myStr = "TestString";
Module.MyStrLen(myStr);
Run Code Online (Sandbox Code Playgroud)
确保你通过旗帜
--绑定
调用 emcc 时。
还有另一种方法,您可以从 JS 对 C++ 堆执行 Malloc,然后进行操作,但上述方法应该更容易。
其他答案没有解决如何从 C++ 返回字符串。下面是通过引用传递字符串将字符串从 C++ 传递到 javascript 的方法。
cwrapemscripten 文档对可以使用/传递给 C/C++ 函数的类型进行了以下说明ccall(emscripten 文档):
类型为“number”(对于对应于 C 整数、浮点或通用指针的 JavaScript 数字)、“string”(对于对应于表示字符串的 C char* 的 JavaScript 字符串)或“array”(对于与 C 数组相对应的 JavaScript 数组或类型化数组;对于类型化数组,它必须是 Uint8Array 或 Int8Array)。
正如其他答案所指出的,您需要使用 C 字符串作为参数来编写 C 函数,因为那是 emscripten API(不是因为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
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为传递给函数时会创建一个副本。因此,您需要显式分配内存并传递指针。Emscripten为此提供了allocateUTF8和函数:UTF8ToString
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
Run Code Online (Sandbox Code Playgroud)
因为我们正在将字符串转换为字符指针,所以我们也可以直接调用该函数,而不使用cwrap( emscripten docs ): Module._stringTest(ptr)。它需要一些额外的步骤,但现在您已将字符串从 C 传递到 javascript。
为了使该示例正常工作,您可能需要使用以下标志进行编译:-sEXPORTED_FUNCTIONS="['_stringTest','_malloc','_free']"和-sEXPORTED_RUNTIME_METHODS="['cwrap','allocateUTF8','UTF8ToString']"。
有更通用的方法为其他类型的数组分配内存(/sf/answers/1674192411/)。
一些想法:
crwapor
ccall?var length = Module.ccall('stringLen', ['string'], 'number');stringLen和?stringTestEXPORTED_FUNCTIONSemcc 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/
希望这有帮助。