Learning WASM #8

前回作ったqjs.wasmとJSON-RPCするプログラムを改良して、dotnetからjsへrpcコール中に、jsからdotnetにrpcコールできるようにした。


これでホスト側に生やしたヘルパー関数をゲスト関数が使える。


もう書いたコードが長くなってきたので全部貼ることはしないけど、いつも通りリポジトリにあげてある。




こんなホスト関数を生やしたクラスを用意して、

public class Host
{
    public async Task<int> HostMethod1(int intParam, float floatParam, string stringParam, ObjParam objParam)
    {
        await Task.Delay(1);
        Console.WriteLine("Invoke HostMethod1");
        Console.WriteLine($"intParam = {intParam}");
        Console.WriteLine($"floatParam = {floatParam}");
        Console.WriteLine($"stringParam = {stringParam}");
        Console.WriteLine($"objParam = {objParam?.Property}");
        return -1;
    }
}

public class ObjParam
{
    public string Property { get; set; }
}


QjsRpcのStartメソッドに渡すと、JS側から呼べるようにしてある。


var dir = AppDomain.CurrentDomain.BaseDirectory;
var rpc = new QjsRpc(dir);
var host = new Host();

rpc.Start(host);

var transformed = await rpc.InvokeAsync<JObject>("transform", new[] { new { name = "iwate" } }, CancellationToken.None);

Console.WriteLine(transformed);

await rpc.CloseWaitAsync();


JS側はdotnet側から呼ぶtransform関数が登録してあって、その中でホストのHostMethod1関数を呼んでいる。

Promiseが解決したら、EJSを実行して、HostMehtod1の結果と混ぜてホストに値を返す。

...
register('transform', function (payload, callback) {
  invoke('HostMethod1', 1, 1.0, 'hello', {property:'propvalue'}).then(function (value) {
    ejs.renderFile('template.ejs', payload, {}, function (err, str) {
      if (err) {
        std.err.puts(err);
      }
      else {
        const transformed = {
          name: payload.name,
          html: str,
          value,
        };
        callback(transformed);
      }
    });
  });
});
...

実行結果はこんな感じ。



Invoke HostMethod1
intParam = 1
floatParam = 1
stringParam = hello
objParam = propvalue
{
  "name": "iwate",
  "html": "<html>\r\n<body>\r\n<p>Hello, Wasmtime! I am iwate.</p>\r\n</body>\r\n</html>",
  "value": -1
}


HostMethod1の出力もあるし、transformedにHostMethod1の結果であるvalue:-1もセットされている。大成功。


いい感じにまとまってきたので、次回はライブラリにしてNuGetに上げようかな。