Skip to content

Instantly share code, notes, and snippets.

@rygo6
Created December 24, 2021 00:12
Show Gist options
  • Save rygo6/536168feb648f88f2cebdde7203e62a4 to your computer and use it in GitHub Desktop.
Save rygo6/536168feb648f88f2cebdde7203e62a4 to your computer and use it in GitHub Desktop.
Marshall string from C# to wasmer.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using WasmerSharp;
public class WASMTests : MonoBehaviour
{
private Memory _memory;
private void Start()
{
RunWASMTest();
}
private void RunWASMTest()
{
Import printFunc = new Import("index", "printExtern", new ImportFunction((Action<InstanceContext, int, int>) Print));
Import getPlatformFunc = new Import("index", "getPlatformExtern", new ImportFunction((Func<InstanceContext, int>) GetPlatform));
_memory = Memory.Create(minPages: 256, maxPages: 256);
Import memoryImport = new Import("env", "memory", _memory);
Import global = new Import("env", "__memory_base", new Global(1024, false));
byte[] wasm = File.ReadAllBytes("AssemblyScript/untouched.wasm");
Instance instance = new Instance(wasm, printFunc, getPlatformFunc, memoryImport, global);
object[] ret = instance.Call("hello_world");
if (ret == null)
Debug.Log($"error calling method {instance.LastError}");
else
Debug.Log("hello_world returned: " + ret);
}
private int GetPlatform(InstanceContext ctx)
{
int offset = 0;
WasmString version = new WasmString($"Unity {Application.platform} {Application.unityVersion}");
Marshal.StructureToPtr(version, ctx.GetMemory(0).Data, true);
return offset;
}
private void Print(InstanceContext ctx, int ptrOffset, int len)
{
IntPtr memoryBase = ctx.GetMemory(0).Data;
// PrintMemory(ctx.GetMemory(0));
string str = Marshal.PtrToStringUni(memoryBase + ptrOffset, len);
Debug.Log($"WASM Print: {str}");
}
private unsafe void PrintMemory(Memory memory)
{
Debug.Log($"Print Memory {memory.DataLength} {memory.PageLength}");
byte* memBytePtr = (byte*) memory.Data.ToPointer();
UnmanagedMemoryStream readStream = new UnmanagedMemoryStream(memBytePtr, 50, 50, FileAccess.Read);
byte[] outMessage = new byte[50];
readStream.Read(outMessage, 0, 50);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 50; i++)
{
sb.AppendLine(outMessage[i].ToString());
}
Debug.Log(sb.ToString());
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1), Serializable]
public class WasmString
{
// Const is not serialized to struct, but needs to be Const to use in MarshalAs Attribute.
public const int MaxCapacity = 64;
public readonly int Length;
public readonly int Capacity;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxCapacity)]
public readonly string Buffer;
public WasmString(string buffer)
{
Buffer = buffer;
Length = Encoding.Unicode.GetByteCount(buffer);
Capacity = MaxCapacity;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment