【Zoom Meeting SDK】Windows SDKのC# Wrapperに新しいインタフェースを追加する。

# はじめに

Zoom Meeting SDKの[Windows SDK](https://marketplace.zoom.us/docs/sdk/native-sdks/windows/)はC++で提供されているのですが、合わせてC#への[Wrapper](https://marketplace.zoom.us/docs/sdk/native-sdks/windows/c-sharp-wrapper)も提供されています。  
しかしながら、このWrapperプロジェクトはC++のインタフェースを完全に含んでいるわけではないとの事です。  
Wrapperに含まれていないインタフェースについては、自力で追加する必要があります。

公式ドキュメントに[インタフェースの追加の仕方](https://marketplace.zoom.us/docs/sdk/native-sdks/windows/c-sharp-wrapper#add-a-new-interface)が記載されてはいるのですが、説明不足なのか私の読解力の問題なのか記載内容に沿ってやると上手くいかなかったので、備忘録としてやり方を残しておきます。

ちなみに筆者はC++未経験、C#は業務で浅く触った程度でしたので、できればC#使いたいなと思い立った次第です。  
C++使い慣れている方、プロジェクトの都合上C++でも問題ない方でしたら普通にC++のまま使った方が良いんじゃないかなぁ…と思いました。

# 前提条件

- Zoom SDKおよびWrapperのバージョン
  - 5.9.7.3953

# ケース
Zoom Meeting SDKのWindows SDKを使って音声データ取得ができないか調査中でしたので、例として以下のような追加をしたいと思います。

- クラス：[IMeetingRecordingController](https://marketplacefront.zoom.us/sdk/meeting/windows/class_i_meeting_recording_controller.html)
  - [StartRawRecording()](https://marketplacefront.zoom.us/sdk/meeting/windows/class_i_meeting_recording_controller.html#afa1976b3de8316ece57f0cb8ded0ac45)
  - [StopRawRecording()](https://marketplacefront.zoom.us/sdk/meeting/windows/class_i_meeting_recording_controller.html#a552a52e2774c2bb43cbfa2ec682a5613)

# 手順
## Wrapperを開く
1. Zoom MarketplaceからWrapperをダウンロードします。
1. ダウンロードしたZipファイルを解凍後、以下をVisual Studioで開きます。
　 `zoom-c-sharp-wrapper-5.9.7.3953\zoom-c-sharp-wrapper-5.9.7.3953\x86\zoom_sdk_c_sharp_wrap\zoom_sdk_c_sharp_wrap.sln`
1. ソリューションを開くと`zoom_sdk_dotnet_wrap`というプロジェクトがあります。これが修正する対象のC# Wrapperです。

## Wrapperを修正する。

追加したい`IMeetingRecordingController`クラスにWrapper上で対応しているファイルは以下になります。
- meeting_recording_wrap.h
- meeting_recording_wrap.cpp
    - 上記2ファイルはドキュメントに記載なかったですが修正必要でした。
- meeting_recording_dotnet_wrap.h
- meeting_recording_dotnet_wrap.cpp

それぞれに対して`StartRawRecording()`, `StopRawRecording()`を追加していきます。

```diff_c_sharp:meeting_recording_wrap.h
// ==== 省略 ====
//virtual SDKError DisAllowLocalRecording(unsigned int userid) = 0;
DEFINE_FUNC_1(DisAllowLocalRecording, SDKError, unsigned int, userid)
//virtual SDKError RequestCustomizedLocalRecordingSource() = 0;
DEFINE_FUNC_0(RequestCustomizedLocalRecordingSource, SDKError)

+ DEFINE_FUNC_0(StartRawRecording, SDKError)
+ DEFINE_FUNC_0(StopRawRecording, SDKError)
// ==== 省略 ====
```

定義しているマクロ`DEFINE_FUNC_0`ですが、追加したいメソッドの引数の数によって使用するマクロが異なります。  
例えば、引数が1つであれば、`DEFINE_FUNC_1`を使用する形です。

```diff_c_sharp:meeting_recording_wrap.cpp
// ==== 省略 ====
//virtual SDKError DisAllowLocalRecording(unsigned int userid) = 0;
IMPL_FUNC_1(IMeetingRecordingController, DisAllowLocalRecording, SDKError, unsigned int, userid, SDKERR_UNINITIALIZE)
//virtual SDKError RequestCustomizedLocalRecordingSource() = 0;
IMPL_FUNC_0(IMeetingRecordingController, RequestCustomizedLocalRecordingSource, SDKError, SDKERR_UNINITIALIZE)
+ IMPL_FUNC_0(IMeetingRecordingController, StartRawRecording, SDKError, SDKERR_UNINITIALIZE)
+ IMPL_FUNC_0(IMeetingRecordingController, StopRawRecording, SDKError, SDKERR_UNINITIALIZE)
// ==== 省略 ====
```

こちらで使用している`IMPL_FUNC_0`についても`DEFINE_FUNC_0`と同様に引数の数で使用するマクロが変わります。

```diff_c_sharp:meeting_recording_dotnet_wrap.h
// ==== 省略 ====
	public interface class IMeetingRecordingControllerDotNetWrap
	{
	public:
		SDKError StartRecording(DateTime^% startTimestamp);
		SDKError StopRecording(DateTime^% stopTimestamp);
		SDKError CanStartRecording(bool cloudRecording, unsigned int userId);
		SDKError CanAllowDisAllowLocalRecording();
		SDKError StartCloudRecording();
		SDKError StopCloudRecording();
		SDKError IsSupportLocalRecording(unsigned int userId);
		SDKError AllowLocalRecording(unsigned int userId);
		SDKError DisAllowLocalRecording(unsigned int userId);
		SDKError RequestCustomizedLocalRecordingSource();
+		SDKError StartRawRecording();
+		SDKError StopRawRecording();
// ==== 省略 ====
	private ref class CMeetingRecordingControllerDotNetWrap : public IMeetingRecordingControllerDotNetWrap
	{
	public:
		static property CMeetingRecordingControllerDotNetWrap^ Instance
		{
			CMeetingRecordingControllerDotNetWrap^ get() { return m_Instance; }
		}

		virtual SDKError StartRecording(DateTime^% startTimestamp);
		virtual SDKError StopRecording(DateTime^% stopTimestamp);
		virtual SDKError CanStartRecording(bool cloudRecording, unsigned int userId);
		virtual SDKError CanAllowDisAllowLocalRecording();
		virtual SDKError StartCloudRecording();
		virtual SDKError StopCloudRecording();
		virtual SDKError IsSupportLocalRecording(unsigned int userId);
		virtual SDKError AllowLocalRecording(unsigned int userId);
		virtual SDKError DisAllowLocalRecording(unsigned int userId);
		virtual SDKError RequestCustomizedLocalRecordingSource();
+		virtual SDKError StartRawRecording();
+		virtual SDKError StopRawRecording();
// ==== 省略 ====
```
`public interface class IMeetingRecordingControllerDotNetWrap`と`rivate ref class CMeetingRecordingControllerDotNetWrap`の両方にメソッド定義を追加してください。

```diff_c_sharp:meeting_recording_dotnet_wrap.cpp
// ==== 省略 ====
	SDKError CMeetingRecordingControllerDotNetWrap::DisAllowLocalRecording(unsigned int userId)
	{
		return (SDKError)ZOOM_SDK_NAMESPACE::CSDKWrap::GetInst().GetMeetingServiceWrap().
			GetMeetingRecordingController().DisAllowLocalRecording(userId);
	}

	SDKError CMeetingRecordingControllerDotNetWrap::RequestCustomizedLocalRecordingSource()
	{
		return (SDKError)ZOOM_SDK_NAMESPACE::CSDKWrap::GetInst().GetMeetingServiceWrap().
			GetMeetingRecordingController().RequestCustomizedLocalRecordingSource();
	}

+	SDKError CMeetingRecordingControllerDotNetWrap::StartRawRecording()
+	{
+		return (SDKError)ZOOM_SDK_NAMESPACE::CSDKWrap::GetInst().GetMeetingServiceWrap().
+			GetMeetingRecordingController().StartRawRecording();
+	}
+
+	SDKError CMeetingRecordingControllerDotNetWrap::StopRawRecording()
+	{
+		return (SDKError)ZOOM_SDK_NAMESPACE::CSDKWrap::GetInst().GetMeetingServiceWrap().
+			GetMeetingRecordingController().StopRawRecording();
+	}
// ==== 省略 ====
```

こちらも上記の通り追加してください。


## プロジェクトをビルドする

ソリューションエクスプローラーの`zoom_sdk_dotnet_wrap`を右クリック > `ビルド`を選択しwrapperをビルドします。

これで以下のdllが更新されるはず。  
`zoom-c-sharp-wrapper-5.9.7.3953\zoom-c-sharp-wrapper-5.9.7.3953\x86\bin\zoom_sdk_dotnet_wrap.dll`

# 終わりに

Zoom SDKですが、日本語の記事などが見つからない上、公式のドキュメントも情報が足りず、かなり苦労しそうな印象です。  
先にも書いた通り、C++ができる方であればSDKをそのまま使用した方が、まだリファレンスがあるのでやりやすいかと思います。  

ちなみに、本来やりたかった[音声データ取得](https://marketplace.zoom.us/docs/sdk/native-sdks/windows/raw-data)のためには、`IZoomSDKAudioRawDataDelegate`というクラスが必要っぽいのですが、Wrapperに含まれていないため追加が必要でした。
今回はメソッドのインタフェースを追加しましたが、使用したいクラス自体がWrapperに不足している場合はどうやって追加すればいいのか…ドキュメントに記載がない…。うーむ。。。