メインコンテンツまでスキップ

生成されたコードを利用する

インターフェース実装をコンポーネントに公開する

インターフェースのメンバとして静的メソッド 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("ぼく", "こんにちは");