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

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

ただいまの
回答率

90.33%

  • C#

    7750questions

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

  • C++

    3792questions

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

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 162

mypace

score 9

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

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

コード
        //--- レンズ歪み補正 ---//
        cv::undistort(dst, dst2, Mtx, Dist);    //L
        DWORD size = dst.dataend - dst.datastart;
        //--- 動画保存 ---//
        writer << dst2;
        cv::imshow("window-cam" + std::to_string(camNo) + "", dst2);//画像を表示.

        //--- dataを配列に格納する ---//
        byte *imgarray = new byte[dst2.rows * dst2.cols * dst2.channels()];    //

        for (int y = 0; y < dst2.rows; y++) {
            // ポインタの取得
            cv::Vec3b* ptr = dst2.ptr<cv::Vec3b>(y);
            for (int x = 0; x < dst2.cols; x++) {
                // 値の取得
                // 対象のピクセルが赤だった場合、BGRの順に"0,0,255"と出力される。
                cv::Vec3b bgr = ptr[x];
                //printf("%d,%d,%d\n", bgr[0], bgr[1], bgr[2]);

                //--- 配列へデータを格納 ---//
                imgarray[(y * dst2.rows) + (3 * x) + 0] = bgr[0];
                imgarray[(y * dst2.rows) + (3 * x) + 1] = bgr[1];
                imgarray[(y * dst2.rows) + (3 * x) + 2] = bgr[2];
            }
        }
        //--- MemoryMappedFile記述 ---//
        //HANDLE hShareMemory = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "ImageAccess");
        HANDLE hShareMemory = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, "ImageAccess");
        if (NULL != hShareMemory) {
            printf("共有メモリオープン成功\n");
            //--- 共有メモリマッピング ---//
            void* cpSharedMemory = ::MapViewOfFile(hShareMemory, FILE_MAP_WRITE, 0, 0, size);    //戻り値 開始アドレス
            if (NULL != cpSharedMemory) {
                printf("共有メモリマッピング成功 %x", (DWORD)cpSharedMemory);        //ハンドル表示

                //--- データコピー ---//
                //memcpy(imgarray, &dst.data, size);
                memcpy(cpSharedMemory, imgarray, sizeof(unsigned char) * size);
                //--- 共有マッピング解除 ---//
                ::UnmapViewOfFile(cpSharedMemory);
            }
            else {
                printf("共有マッピング失敗\n");
            }

        }
        else {
            printf("共有メモリオープン失敗\n");
        }
        //--- ファイルマッピングオブジェクトハンドルの開放 ---//
        if (NULL != hShareMemory) {
            printf("共有メモリクローズ\n");
            ::CloseHandle(hShareMemory);

        }

```

コード  
string mappedName = "ImageAccess";  
MemoryMappedFile mmf;  
try  
{  
//--- メモリマップドファイルを開く ---//  
using (mmf = MemoryMappedFile.CreateNew(mappedName, width * height * 5, MemoryMappedFileAccess.ReadWrite))  
{  

//C++側 マップ書き込み ※FilePathを可変的な記述へ変更のこと  

string filePath = "C:\\images";  

int check = RecVideoL(camNo, width, height, fps, filePath, mappedName);  
//}  
//--- マップドストリーム作成 マップ操作 ---//  
using (MemoryMappedViewStream stream = mmf.CreateViewStream())  
{  

//C#側 マップデータ読み込み  
stream.Read(imageArr, 0, sizeof(byte) * width * height * 4);  

//C#側 BMP変換  

ImageConverter imgConv = new ImageConverter();  
if (imgConv != null)  
{  
Image img = (Image)imgConv.ConvertFrom(imageArr);  
Bitmap bmp = new Bitmap(img);  
//PictureBoxへの表示  
CameraImg.Image = bmp;  
}  
}  
}  

}  
catch (Exception ex)  
{  
MessageBox.Show(ex.Message);  
this.Close();  
}  
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • takabosoft

    2018/12/07 16:51

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

    キャンセル

  • mypace

    2018/12/08 15:26

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

    キャンセル

回答 1

checkベストアンサー

+1

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

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

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

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

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

送信側(c++, MFC):

void CMappedFileSendDlg::OnBnClickedButton1()
{
    DWORD dwSharedMemorySize = 1024;
    HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, dwSharedMemorySize, _T("HOGEHOGE"));
    if (hFileMapping) {
        BYTE* pBytes = (BYTE*)::MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, dwSharedMemorySize);
        if (pBytes) {
            for (DWORD i = 0; i < 1024; i++) {
                pBytes[i] = (BYTE)i;
            }
            UnmapViewOfFile(pBytes);
        }
        AfxMessageBox(_T("作成済み"));
        CloseHandle(hFileMapping);
    }
}

受信側(C#, WinForms):

        private void button1_Click(object sender, EventArgs e)
        {
            using (var mmf = MemoryMappedFile.OpenExisting("HOGEHOGE"))
            using (var stream = mmf.CreateViewStream())
            {
                byte[] bytes = new byte[1024];
                if (stream.Read(bytes, 0, 1024) == 1024)
                {
                    foreach (var b in bytes)
                    {
                        Debug.WriteLine(b);
                    }
                }
            }
        }

出力結果:

0
1
2
3
4
5
6
7
8
9
...
(略)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/12 19:27

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

    キャンセル

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

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C#

    7750questions

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

  • C++

    3792questions

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