FastVM / Web49

Web49: WebAssembly Interpeter
MIT License
322 stars 15 forks source link

Help with passing string to imported function #14

Closed konsumer closed 11 months ago

konsumer commented 11 months ago

I have a function that takes a string param, like this:

uint32_t font_measure(uint32_t fontID, char* text);

That I am trying to expose, like this:

static web49_interp_data_t wasi_import_font_measure(void* wasi_untyped, web49_interp_t interp) {
  uint32_t fontID = interp.locals[0].i32_u;
  uint32_t textPtr = interp.locals[1].i32_u;
  char text[512];
  memcpy(text, WEB49_INTERP_ADDR(void *, interp, textPtr, 512), 512);
  return (web49_interp_data_t){.i32_u = font_measure(fontID, text)};
}

This works, but seems like the wrong way to me (using max-length of 512 to pull the whole thing.) Is this the right way to pull the string? Is there a better way to get the string-length up-front? Should I rewrite all functions that take string params to include length param, too?

ShawSumma commented 11 months ago

char * by definition has no builtin length, if you want a length you can either pass one or do pascal-style strings. WASM strings are kinda a mess right now.

konsumer commented 11 months ago

Yeh, for sure. I see that WASI includes length-param on all of their string-param functions, but I can generally get by with /0-delimited strings, elsewhere. I was hoping to not have to change my import ABI, but that makes sense.

Like on wasm-side I can change to this, even though I was hoping I could avoid that:

uint32_t font_measure(uint32_t fontID, char* text, uint32_t textLength);
ShawSumma commented 11 months ago

I would put the length first, but yea that would work. Also strlen if you null terminate.

ShawSumma commented 11 months ago

WASM doesn't segment memory at all, you get a buffer. you can even write to NULL 😨... I'm gonna close this issue in a bit unless there's anything else relevant.

konsumer commented 11 months ago

So it would look like this?

len = strlen(WEB49_INTERP_ADDR(void *, interp, textPtr, MAX_STRING_SIZE));

Like that macro copies the buffer, so I have to take MAX_STRING_SIZE, right?

konsumer commented 11 months ago

Ah, sorry, nevermind, just saw this:

size_t memlen = strlen(wasi->argv[i]) + 1;
memcpy(WEB49_INTERP_ADDR(void *, interp, head2, memlen), wasi->argv[i], memlen);

Thanks!