前回作った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に上げようかな。