mJS: converting a C buffer into a JS string

I have a set of C functions which take a pointer to a buffer and a size for that buffer, e.g:

int getString1(char *pBuffer, int size);

The functions all return an integer which indicates success (== 0) or error (!= 0) and place a standard C string into pBuffer, making sure it is terminated within size bytes with a null byte.

I would like to map these into JS functions which return an object containing error (an integer) and value (a JS string), something like:

function getGenericString(fnName) {
    // Create buffer here
    let cCall = ffi(fnName);
    return {
        error: // something like cCall(buffer, lengthOfBuffer),
        value: // convert buffer into JS string somehow here
    };
}

In mJS, how do I create the necessary fixed-length buffer to pass into the C function and what mJS function do I use to turn the null-terminated string that buffer contains into a true JS string?

1 Like

I might have an ideea:
C code:

int string_test(char *buf, int buf_len) {
  const char *string = mgos_sys_config_get_app_string();
  if (strlen(string) < buf_len) {
    strcpy(buf, string);
    return 0;
  }
  return -1;
}

mJS code:

load('api_sys.js');

function getGenericString(fnName, buf_len) {
  let strlen = ffi('int strlen(void*)');
  let buf = Sys.malloc(buf_len);
  let cCall = ffi(fnName);
  let ret_val = cCall(buf, buf_len);
  let ret = {error: 0, value: ''};
  if (ret_val === 0) {
    ret.value = mkstr(buf, 0, strlen(buf), true);
  } else {
    ret.error = ret_val;
  }
  Sys.free(buf);

  return ret;
}

function run_tests() {
  let ret = getGenericString('int string_test(void*, int)', 10);
  print(JSON.stringify(ret));
  ret = getGenericString('int string_test(void*, int)', 20);
  print(JSON.stringify(ret));
}

Results:

[May 10 14:06:19.896] {"value":"","error":-1}
[May 10 14:06:19.906] {"value":"123456abcdefgh","error":0}
2 Likes

Aaah, interesting, I’d not noticed the existence of Sys.malloc() and Sys.free(). I had noticed mkstr() but hadn’t figured out how to get a pointer to some memory for it: having a JS-level malloc() and free() is what I needed! I’ll give that a go.

Many thanks for the swift and useful response.