生成されたコードを利用する
インターフェース実装をコンポーネントに公開する
インターフェースのメンバとして静的メソッド CreateWaaSInstance()
が定義されるので、こちらを使います。
// <auto-generated />
partial interface IEnv
{
public static IInstance CreateWaaSInstance(IEnv target);
}
CreateWaaSInstance()
は、C# で実装されたインターフェースをラップして IInstance
に変換するメソッドです。
IInstance
に変換することで、コンポーネントのインスタンス化時にインポートできるようになります。
コンポーネントに必要な実装を C# 側から提供したい場合に使用できます。
var component = LoadComponent();
var instance = component.Instantiate(null, new Dictionary<string, ISortedExportable>()
{
{ "my-game:my-sequencer/env", IEnv.CreateWaaSInstance(new EnvImpl()) }
});
public class EnvImpl : IEnv { /* ここを実装 */ }
所有権のハンドリング
引数として Owned<T>
が C# コードに渡される場合、以下のいずれかを行う必要があります。
Owned<T>.Dispose()
による所有権の破棄Owned<T>
をさらに他の関数に渡すことによる所有権の移譲
これを行わない場合、リソースがリークします。
リソースを C# のオブジェクトに紐づける
リソース型の実装を C# 側で提供する場合、リソースを C# のオブジェクトに紐づけることができます。
リソースを C# のオブジェクトに紐づけるには、リソース型の実装クラスで HostResourceTypeBase<T>
を継承します。
Wrap()
または Unwrap()
メソッドを使用して、リソース型と C# のオブジェクトを変換できます。
using WaaS.ComponentModel.Binding;
using WaaS.ComponentModel.Runtime;
using System;
using System.IO;
[ComponentInterface(@"env")]
public partial interface IEnv
{
[ComponentResource(@"stream")]
public partial interface IStreamResourceImpl : IResourceImpl
{
[ComponentApi("[constructor]stream")]
Owned<IStreamResourceImpl> Create();
[ComponentApi("[method]stream.write-byte")]
void WriteByte(Borrowed<IStreamResourceImpl> self, byte value);
}
}
public class StreamResourceType : HostResourceTypeBase<Stream>, IEnv.IStreamResourceImpl
{
public Owned<IEnv.IStreamResourceImpl> Create()
{
var stream = File.Open("hoge.txt", FileMode.Create, FileAccess.Write);
// Stream -> Owned<IStreamResourceImpl>
var handle = Wrap<IEnv.IStreamResourceImpl>(stream);
return handle;
}
public void WriteByte(Borrowed<IEnv.IStreamResourceImpl> self, byte value)
{
// Borrowed<IStreamResourceImpl> -> Stream
var stream = Unwrap(self);
stream.WriteByte(value);
}
public IResourceType Type => this;
}
public class EnvImpl : IEnv
{
public IEnv.IStreamResourceImpl Stream { get; } = new StreamResourceType();
}
Wrap()
で Owned<T>
を作成すると、内部のテーブルから対象のオブジェクトが参照されます。
Owned<T>
を確実に戻り値として返すことで、その後リソースが不要になったタイミングで参照が解放されます。Owned<T>
を作成したまま返さずにいるとメモリリークするので注意してください。
コンポーネントが公開する関数を呼び出す
インターフェースのメンバとして、構造体 Wrapper
が定義されるので、こちらを使います。
// <auto-generated />
partial interface IEnv
{
public readonly struct Wrapper : IEnv
{
public Wrapper(IInstance instance, ExecutionContext context);
public ValueTask ShowMessage(string @speaker, string @message);
public ValueTask<uint> ShowOptions(ReadOnlyMemory<string> @options)
}
}
Wrapper
は、外部で作成した IInstance
をラップし、IEnv
に変換する構造体です。
対象のインスタンスが IEnv
に対応する関数等をエクスポートしていることが前提となります(自動的なチェックは行われません)。
コンポーネントがエクスポートする関数を C# から呼び出す際に使用できます。
var component = await componentAsset.LoadComponentAsync();
var instance = component.Instantiate(null, new Dictionary<string, ISortedExportable>());
using var context = new ExecutionContext();
var wrapper = new IEnv.Wrapper(instance, context);
await wraapper.ShowMessage("ぼく", "こんにちは");