質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

9477閲覧

プロセス間通信でC++の画像データをC#へ渡したいです。

mypace

総合スコア45

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/12/05 12:42

編集2018/12/08 06:26

C++dllのOpenCVによって得た画像データを、プロセス間通信をおこないC#へ渡したいです。
共有メモリは動いているようですが、C#側のStreamReadにデータが入っておらず、
全ての要素に0が入っている状態です。

C#側へデータを配列で渡す方法、または
配列以外でデータを渡すよい方法など、ご教授いただきたく思います。

C++

1コード 2 //--- レンズ歪み補正 ---// 3 cv::undistort(dst, dst2, Mtx, Dist); //L 4 DWORD size = dst.dataend - dst.datastart; 5 //--- 動画保存 ---// 6 writer << dst2; 7 cv::imshow("window-cam" + std::to_string(camNo) + "", dst2);//画像を表示. 8 9 //--- dataを配列に格納する ---// 10 byte *imgarray = new byte[dst2.rows * dst2.cols * dst2.channels()]; // 11 12 for (int y = 0; y < dst2.rows; y++) { 13 // ポインタの取得 14 cv::Vec3b* ptr = dst2.ptr<cv::Vec3b>(y); 15 for (int x = 0; x < dst2.cols; x++) { 16 // 値の取得 17 // 対象のピクセルが赤だった場合、BGRの順に"0,0,255"と出力される。 18 cv::Vec3b bgr = ptr[x]; 19 //printf("%d,%d,%d\n", bgr[0], bgr[1], bgr[2]); 20 21 //--- 配列へデータを格納 ---// 22 imgarray[(y * dst2.rows) + (3 * x) + 0] = bgr[0]; 23 imgarray[(y * dst2.rows) + (3 * x) + 1] = bgr[1]; 24 imgarray[(y * dst2.rows) + (3 * x) + 2] = bgr[2]; 25 } 26 } 27 //--- MemoryMappedFile記述 ---// 28 //HANDLE hShareMemory = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "ImageAccess"); 29 HANDLE hShareMemory = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, "ImageAccess"); 30 if (NULL != hShareMemory) { 31 printf("共有メモリオープン成功\n"); 32 //--- 共有メモリマッピング ---// 33 void* cpSharedMemory = ::MapViewOfFile(hShareMemory, FILE_MAP_WRITE, 0, 0, size); //戻り値 開始アドレス 34 if (NULL != cpSharedMemory) { 35 printf("共有メモリマッピング成功 %x", (DWORD)cpSharedMemory); //ハンドル表示 36 37 //--- データコピー ---// 38 //memcpy(imgarray, &dst.data, size); 39 memcpy(cpSharedMemory, imgarray, sizeof(unsigned char) * size); 40 //--- 共有マッピング解除 ---// 41 ::UnmapViewOfFile(cpSharedMemory); 42 } 43 else { 44 printf("共有マッピング失敗\n"); 45 } 46 47 } 48 else { 49 printf("共有メモリオープン失敗\n"); 50 } 51 //--- ファイルマッピングオブジェクトハンドルの開放 ---// 52 if (NULL != hShareMemory) { 53 printf("共有メモリクローズ\n"); 54 ::CloseHandle(hShareMemory); 55 56 } 57

C#

1コード 2 string mappedName = "ImageAccess"; 3 MemoryMappedFile mmf; 4 try 5 { 6 //--- メモリマップドファイルを開く ---// 7 using (mmf = MemoryMappedFile.CreateNew(mappedName, width * height * 5, MemoryMappedFileAccess.ReadWrite)) 8 { 9 10 //C++側 マップ書き込み ※FilePathを可変的な記述へ変更のこと 11 12 string filePath = "C:\images"; 13 14 int check = RecVideoL(camNo, width, height, fps, filePath, mappedName); 15 //} 16 //--- マップドストリーム作成 マップ操作 ---// 17 using (MemoryMappedViewStream stream = mmf.CreateViewStream()) 18 { 19 20 //C#側 マップデータ読み込み 21 stream.Read(imageArr, 0, sizeof(byte) * width * height * 4); 22 23 //C#側 BMP変換 24 25 ImageConverter imgConv = new ImageConverter(); 26 if (imgConv != null) 27 { 28 Image img = (Image)imgConv.ConvertFrom(imageArr); 29 Bitmap bmp = new Bitmap(img); 30 //PictureBoxへの表示 31 CameraImg.Image = bmp; 32 } 33 } 34 } 35 36 } 37 catch (Exception ex) 38 { 39 MessageBox.Show(ex.Message); 40 this.Close(); 41 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takabosoft

2018/12/07 07:51

C#側の「mmf」の初期化コードも載せてください。
mypace

2018/12/08 06:26

mmfの初期化コードを追加いたしました。
guest

回答1

0

ベストアンサー

こういう課題の場合、シンプルなプロジェクトを作ってプロセス間通信部分のみの技術調査を行う事が大事です。

自分でもやってみましたが、

  1. C++側がhShareMemory::CloseHandle(hShareMemory);した時点でマップファイルは消去され、C#側では読めなくなりました。つまりhShareMemoryはクラスのメンバで管理するなどして、なるべく開きっぱなしの方がよいです。
  2. C#側でMemoryMappedFile.CreateNewを使っていますが、これはすでに作成したマップファイルを開くものではなく新規に作成する関数です。作成済みのものを開くのであればMemoryMappedFile.OpenExistingを使えば良さそうです。

...ということが判りましたので、その辺を考慮して修正を行ってください。

以下、検証用コードです。

送信側(c++, MFC):

cpp

1void CMappedFileSendDlg::OnBnClickedButton1() 2{ 3 DWORD dwSharedMemorySize = 1024; 4 HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, dwSharedMemorySize, _T("HOGEHOGE")); 5 if (hFileMapping) { 6 BYTE* pBytes = (BYTE*)::MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, dwSharedMemorySize); 7 if (pBytes) { 8 for (DWORD i = 0; i < 1024; i++) { 9 pBytes[i] = (BYTE)i; 10 } 11 UnmapViewOfFile(pBytes); 12 } 13 AfxMessageBox(_T("作成済み")); 14 CloseHandle(hFileMapping); 15 } 16}

受信側(C#, WinForms):

csharp

1 private void button1_Click(object sender, EventArgs e) 2 { 3 using (var mmf = MemoryMappedFile.OpenExisting("HOGEHOGE")) 4 using (var stream = mmf.CreateViewStream()) 5 { 6 byte[] bytes = new byte[1024]; 7 if (stream.Read(bytes, 0, 1024) == 1024) 8 { 9 foreach (var b in bytes) 10 { 11 Debug.WriteLine(b); 12 } 13 } 14 } 15 }

出力結果:

text

10 21 32 43 54 65 76 87 98 109 11... 12(略)

投稿2018/12/10 02:47

編集2018/12/10 03:23
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mypace

2018/12/12 10:27

アドバイスいただきありがとうございます。 検証してプロセス間通信ができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問