Reputation: 191
I am trying to write a web application that will do sort of word processing (say spell check, grammar check, word analysis) using back-end C/C++ code. (I have got c/C++ code working in another desktop app... I want to bring it to web). I want an example minimal code doing this (pass array of strings from JavaScript to c/c++ code...c/c++ code will do the word operations... I have this code ......and the resulting array of strings will be sent back to JavaScript where they will be processed further. (passing arrays to and from is important) Please point me to any such code/tutorial, from where I can make a start.
I searched GitHub. I found several projects using emscripten but could not get this anywhere. (Only place I could get some clue was Hunspell built with emscripten ... however I could not build it successfully)
Please let me know . Thanks in advance.
Upvotes: 5
Views: 1068
Reputation: 1579
First prepare the C++ side to receive a string (character array):
static char *string_buffer = NULL;
static size_t string_length = 0;
void EMSCRIPTEN_KEEPALIVE string_start_js(void) {}
void EMSCRIPTEN_KEEPALIVE string_final_js(void) {}
char * EMSCRIPTEN_KEEPALIVE string_ensure(size_t length)
{
// ensure that the buffer is long enough
if (length <= string_length) return string_buffer;
// grow the buffer
char *new_buffer = realloc(string_buffer, length + 1);
// handle the out of memory
if (new_buffer == null) return NULL;
// remember
string_buffer = new_buffer;
string_length = length;
// done
return string_buffer;
}
void EMSCRIPTEN_KEEPALIVE string_handle(size_t length)
{
// sanity
if (string_buffer == NULL || length > string_length) halt;
// terminate
string_buffer[length] = 0;
// work with the string characters, store/process it
}
void EMSCRIPTEN_KEEPALIVE string_clear(void)
{
// friendly
if (string_buffer == NULL) return;
// free
free(string_buffer);
// remember
string_buffer = NULL;
string_length = 0;
}
From the JavaScript side send one string to the C++ side:
let strings = ["abc", "defg", "1"];
// inform the C++ side that some strings are going to be transferred
exports['string_start_js']();
// send all strings
for (var i = 0; i < strings.length; i++)
{
// single string to transport
let string = strings[i];
// convert to a byte array
let string_bytes = new TextEncoder().encode(string);
// ensure enough memory in the C++ side
let string_offset = exports["string_ensure"](string_bytes.byteLength);
// handle the out of memory
if (string_offset == 0) throw "ops...";
// have view of the instance memory
let view = new Uint8Array(memory.buffer, string_offset, string_bytes.byteLength);
// copy the string bytes to the memory
view.set(string_bytes);
// handle
exports['string_handle'](string_bytes.byteLength);
}
// inform the C++ side that all strings were transferred
exports['string_final_js']();
// clear the used buffer
exports['string_clear']();
The way from C++ to WASM can be more simple:
view
of the memoryview
Something like this in the C++ side:
extern "C" {
extern void string_start_cpp(void);
extern void string_final_cpp(void);
extern void string_fetch(char *pointer, size_t length);
}
void foo(void)
{
// inform the JavaScript side that
string_start_cpp();
// runtime string
const char *demo = "abc";
// send to JavaScript
string_fetch(demo, strlen(demo));
// inform the JavaScript side all strings were send
string_final_cpp();
}
And in JavaScript supply the functions during the instance creation:
string_start_cpp: function(offset, length)
{
console.log("{");
},
string_final_cpp: function(offset, length)
{
console.log("}");
},
string_fetch: function(offset, length)
{
// view the bytes
let view = new Uint8Array(memory.buffer, offset, length);
// convert the UTF-8 bytes to a string
let string = new TextDecoder().decode(view);
// use
console.log(string);
}
I did not test the code, there could be some syntax errors. You can improve in many places the code, but the idea is what counts.
Upvotes: 2