问题
I am learning emscripten, and I can't even get the most basic string manipulation working, when passing strings between C++ and JS.
For example, I would like to write a string length function. In C++:
extern "C" int stringLen(std::string p)
{
return p.length();
}
Called from javascript as:
var len = _stringLen("hi.");
This yields 0
for me. How do I make this work as expected? Which string type should I use here? char const*
? std::wstring
? std::string
? None seem to work; I always get pretty random values.
This is only the beginning... How do I then return a string from C++ like this?
extern "C" char *stringTest()
{
return "...";
}
And in JS:
var str = _stringTest();
Again, I cannot find a way to make this work; I always get garbage in JS.
So my question is clearly: How do I marshal string types between JS and C++ via Emscripten?
回答1:
extern "C" doesn't recognize std::string.
You may want to try this:
Test.cpp
#include <emscripten.h>
#include <string.h>
extern "C" int stringLen(char* p)
{
return strlen(p);
}
Use the following command to compile the cpp code :
emcc Test.cpp -s EXPORTED_FUNCTIONS="['_stringLen']
Sample test code :
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>
回答2:
If you use extern "C" with a function, you cannot use C++ types in it's signature.
So if you want to use std::string, then you can use "Embind" or "WebIDL Binder". Refer here
I prefer embind, so this is a sample code for your problem.
P.S I am not sure how to pass variables by reference here, so doing it by value.
// 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);
}
Now in JS all you need to do is:
var myStr = "TestString";
Module.MyStrLen(myStr);
Make sure you pass the flag
--bind
when calling emcc.
There is another approach where you can do a Malloc on the C++ heap from JS and then do manipulations, but the above approach should be easier.
回答3:
A few thoughts:
- The only way I have called a method is by using
crwap
orccall
?var length = Module.ccall('stringLen', ['string'], 'number');
- Are you including
stringLen
andstringTest
in yourEXPORTED_FUNCTIONS
parameter?emcc hello_world.cpp ... -s EXPORTED_FUNCTIONS=['_stringLen','_stringTest']
Take a look here for more details:
http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html
Or my hello_world tutorial:
http://www.brightdigit.com/hello-emscripten/
Hopefully that helps.
来源:https://stackoverflow.com/questions/21816960/how-to-pass-strings-between-c-and-javascript-via-emscripten