I wrote this simple piece of C code:
#include <string.h>
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
const char * helloWorldStatic( ) {
return "Hello World from C";
}
EMSCRIPTEN_KEEPALIVE
char * helloWorldDynamic( ) {
return strdup("Hello World from C");
}
Now when I compile that to WASM32 using Emscripten, I can access either function from TypeScript like this:
async function helloWorldStatic( ): Promise<String>
{
let module = await Module
let result = module.ccall(
"helloWorldStatic", // name of the C function
"string", // return type
[ ], // argument types
[ ] // arguments
)
return result
}
This seems to work fine. When printing the string, I get the expected value.
But what about the memory management? I found nothing in the docs explaining the memory management when using ccall or cwrap the return value is a string.
Does Emscripten always assume all strings are static and never need to be freed? Does it assume they are dynamic and will always free them?
In this example it may assume that const char * needs no freeing, but even if totally lie about it:
EMSCRIPTEN_KEEPALIVE
char * helloWorldStatic( ) {
return "Hello World from C";
}
EMSCRIPTEN_KEEPALIVE
const char * helloWorldDynamic( ) {
return strdup("Hello World from C");
}
It still seems to work. I'm not sure if strings are freed and the code just doesn't crash when trying to free the constant string or if strings just leak that way.
ccallorcwrapwith astringreturn type as if you do that, you lose the only reference to the string you ever had in C and thus you cannot ever release that memory in C. Then you must do it as shown in my answer and return just a pointer and create the JS string yourself. This means thestringreturn type ofccall/cwrapcan only be used for static strings or strings that were not explicitly created as a result but existed already prior to even making the call.