ひとつのUSBカメラをC#とC++で同時に画像を受け取る方法を教えてください


通常、C#等でOpencvとかでUSBカメラを開くとそのUSBカメラのデバイスは占有されるため、他のアプリで開くことはできないと承知しています。  
ですが、ひとつのUSBカメラから流れてくる画像をC#(WPF)とC++(コンソール)のそれぞれで受け取りたい事情があり、どうすることが最も良いのでしょうか。  
現在、C++はOpencvでC#はOpencvSharpで受け取っており問題はありません。  
良いアイディアをお持ちであればご教示いただけますでしょうか。  
よろしくお願いいたします。




頻繁に更新される動画像データを複数のアプリ（プロセス）で共有するのであれば、共有メモリ（メモリマップトファイル）を使うのがベストだと思います。小規模なデータであればソケットやパイプを使う手もありますが。

まず、カメラのキャプチャ（動画像の取得）を実行しているメインアプリ（プロセスA）側で、システムメモリ上に名前付きのメモリマップトファイルを作成します。メモリマップトファイルに、カメラから取得したフレーム画像データを適当なフォーマットで書き込みます（例えば24bpp
RGBや8bppグレースケールのDIB形式など）。  
サブアプリ（プロセスB）側で、必要なときにそのメモリマップトファイルを開いて読み書きします。  
メモリマップトファイルを頻繁に作成・破棄するのはオーバーヘッドが大きいので、一度作成した後は（画像のサイズやピクセルフォーマットの変更がない限り）破棄せず使いまわすようにします。  
お互いのプロセスの読み書き処理はミューテックスを使って排他制御する必要があります。ロックしている間は相手プロセスを待たせることになるので、読み書きが終わったら速やかにロックを解除する必要があります。  
詳しくは以下を参照してください。

  * [メモリ マップト ファイル - .NET | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/standard/io/memory-mapped-files#non-persisted-memory-mapped-files)
  * [Sharing Files and Memory - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/memory/sharing-files-and-memory)

.NETの[`MemoryMappedFile.CreateNew()`](https://learn.microsoft.com/en-
us/dotnet/api/system.io.memorymappedfiles.memorymappedfile.createnew)と[`MemoryMappedFile.OpenExisting()`](https://learn.microsoft.com/en-
us/dotnet/api/system.io.memorymappedfiles.memorymappedfile.openexisting)は、Win32
APIの[`CreateFileMappingW()`](https://learn.microsoft.com/en-
us/windows/win32/api/memoryapi/nf-memoryapi-
createfilemappingw)と[`OpenFileMappingW()`](https://learn.microsoft.com/en-
us/windows/win32/api/memoryapi/nf-memoryapi-openfilemappingw)に相当します。  
.NETの[`System.Threading.Mutex`](https://learn.microsoft.com/en-
us/dotnet/api/system.threading.mutex)は[Win32
Mutex](https://learn.microsoft.com/en-us/windows/win32/sync/mutex-
objects)に相当します。

おそらくC++側は.NET（C++/CLI）ではなくネイティブ（標準C++）だと思いますが、異なる言語や異なるAPIを使い、しかもプロセス間通信をするのは相当にハードルが高いので、まずは同じ言語と同じAPIを使ってプロトコル（通信のデータフォーマットとシーケンス）を確立してから、異なる言語と異なるAPIを使うことに挑戦するようにしたほうがよいです。




頻繁に更新される動画像データを複数のアプリ（プロセス）で共有するのであれば、共有メモリ（メモリマップトファイル）を使うのがベストだと思います。小規模なデータであればソケットやパイプを使う手もありますが。

まず、カメラのキャプチャ（動画像の取得）を実行しているメインアプリ（プロセスA）側で、システムメモリ上に名前付きのメモリマップトファイルを作成します。メモリマップトファイルに、カメラから取得したフレーム画像データを適当なフォーマットで書き込みます（例えば24bpp
RGBや8bppグレースケールのDIB形式など）。  
サブアプリ（プロセスB）側で、必要なときにそのメモリマップトファイルを開いて読み書きします。  
メモリマップトファイルを頻繁に作成・破棄するのはオーバーヘッドが大きいので、一度作成した後は（画像のサイズやピクセルフォーマットの変更がない限り）破棄せず使いまわすようにします。  
お互いのプロセスの読み書き処理はミューテックスを使って排他制御する必要があります。ロックしている間は相手プロセスを待たせることになるので、読み書きが終わったら速やかにロックを解除する必要があります。  
詳しくは以下を参照してください。

  * [メモリ マップト ファイル - .NET | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/standard/io/memory-mapped-files#non-persisted-memory-mapped-files)
  * [Sharing Files and Memory - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/memory/sharing-files-and-memory)

.NETの[`MemoryMappedFile.CreateNew()`](https://learn.microsoft.com/en-
us/dotnet/api/system.io.memorymappedfiles.memorymappedfile.createnew)と[`MemoryMappedFile.OpenExisting()`](https://learn.microsoft.com/en-
us/dotnet/api/system.io.memorymappedfiles.memorymappedfile.openexisting)は、Win32
APIの[`CreateFileMappingW()`](https://learn.microsoft.com/en-
us/windows/win32/api/memoryapi/nf-memoryapi-
createfilemappingw)と[`OpenFileMappingW()`](https://learn.microsoft.com/en-
us/windows/win32/api/memoryapi/nf-memoryapi-openfilemappingw)に相当します。  
.NETの[`System.Threading.Mutex`](https://learn.microsoft.com/en-
us/dotnet/api/system.threading.mutex)は[Win32
Mutex](https://learn.microsoft.com/en-us/windows/win32/sync/mutex-
objects)に相当します。

おそらくC++側は.NET（C++/CLI）ではなくネイティブ（標準C++）だと思いますが、異なる言語や異なるAPIを使い、しかもプロセス間通信をするのは相当にハードルが高いので、まずは同じ言語と同じAPIを使ってプロトコル（通信のデータフォーマットとシーケンス）を確立してから、異なる言語と異なるAPIを使うことに挑戦するようにしたほうがよいです。

