How to read and write strings to memory with a compiled WASM?
Hi. I have a compiled WASM and I'm loading it through the following code.
using System;
using System.Runtime.InteropServices;
using WebAssembly.Runtime;
ImportDictionary imports = new ImportDictionary { };
WebAssembly.Instance<InternalService> instance = Compile.FromBinary<InternalService>("../../target/wasm32-unknown-unknown/release/service.wasm")(imports);
String str = "Hello World!";
int pointer = instance.Exports.alloc(Encoding.ASCII.GetByteCount(str) + 1);
// How to write the the string to the memory?
I would like to write the string str to the linear memory of the WASM instance. However, I have not been able to find any resources on how I can do that. Any help would be highly appreciated.
I was wanting to do this too, and I have some test code for it that I could put in a gist for you. Briefly, you simply need to choose an encoding and then write it into memory with Marshal.Copy.
However, the very next thing you're going to need to think about is what you intend to do with the string once it is in the linear memory. Do you want to compare it or perform some other operation in wasm? Or do you want to get it out at a later point?
What you want to do with it will determine what other primitive operations, such as a string comparison algorithm, which needs to take into account the string encoding, that you will need.
One thing that makes this easier on recent versions of .NET is the Span<T>) type (and the related ReadOnlySpan). One of the constructors takes a Void* parameter, which can be obtained via the Start property of exported memory. From there, Slice it to the appropriate range for the string's bytes (either predefined statically or exported some other way) and use it with Encoding.ASCII/UTF8/etc to read or write from it without having to dabble in pointers or other forms of raw memory access.
One thing that makes this easier on recent versions of .NET is the
Span<T>) type (and the related ReadOnlySpan). One of the constructors takes aVoid*parameter, which can be obtained via theStartproperty of exported memory. From there,Sliceit to the appropriate range for the string's bytes (either predefined statically or exported some other way) and use it with Encoding.ASCII/UTF8/etc to read or write from it without having to dabble in pointers or other forms of raw memory access.
Oh, that's awesome!! A very useful technique
Yeah, it's extremely useful and didn't exist when I first started development (this project's first commit is April 2017, Span came with .NET Core/Standard 2.1 in May 2018).
I've considered replacing most of the internal raw memory usage with Span-based mechanisms, but I'd have to give up .NET Standard 2.0 compatibility or use a lot of conditional compilation. Doesn't seem worth the trouble right now.
In the nearer term, I could potentially add an example on how handle strings with the help of Span.
You might be able to use Span and still keep .net standard 2.0. It sounds like the full benefit isn't there but that it could help.
https://github.com/dotnet/corefxlab/issues/2581