- - PR -
C#からC++へのプロセス間通信
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-06-08 11:15
独立したC#のアプリとC++のアプリ間で値の受け渡しを行いたいと思ってます。
具体的には、C#からPostMessageを用いて文字もしくは数値を受け渡そうと考えていたのですが、 C++側でうまく値を受け取ることができません。 良い方法をご存知でないでしょうか? ---------------サンプルの抜粋---------------------------------- [C#]送信側 [DllImport("user32.dll", SetLastError = true)] private static extern int PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); System.IntPtr HWND_BROADCAST = new IntPtr(0xffff); private UInt32 MyMsg = RegisterWindowMessage("MY_MSG"); //処理を行って送りたい情報(strInfo)をポストする string strInfo = "送りたい情報が処理によって格納される予定"; PostMessage(HWND_BROADCAST, MyMsg, 0, Marshal.StringToHGlobalAnsi(strInfo)); [C++]受信側 UINT MyMsg = RegisterWindowMessage(L"MY_MSG"); INT CALLBACK Proc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) { if(Message == MyMsg) { //受け取った情報を目視するためにエディットボックスに表示 SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)lParam); } } ---------------ここまで---------------------------------- 私なりに、送受信する情報の型が悪いのだろうと思っているのですが、対処法が見当が付かない状態です。 送信側のIntPtrへの変換 受信側のlParamの処理 など ・イベントの受信はできていることは確認できています。 SendDlgItemMessageをBeep関数に置き換えてBeep音を確認より。 ・またイベント情報を無視したエディットボックスの表示(TEST)も確認しています。 SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)L"TEST"); //表示OK 何か良い方法や解決方法があればご教授お願いいたします。 | ||||||||||||
|
投稿日時: 2006-06-08 11:24
プロセスが異なればメモリ空間も異なるので、A プロセスの M というメモリアドレスに存在する文字列を指定しても、B プロセスの方の M というメモリアドレスには文字列は存在しません。
| ||||||||||||
|
投稿日時: 2006-06-08 11:29
文字列が短いなら、GlobalAtomという手もあるね。
| ||||||||||||
|
投稿日時: 2006-06-08 11:30
#単なるコーディングミスだと思う人 ノシ 別プロセスである以上、メモリ空間も独立しています。メモリアドレスを、別のプロセスに単純に渡したって、データを取得できるわけありません。これは言語に関係ない話です。WM_SETTEXTとWM_COPYDATAだけが例外で、メモリアドレスを渡すことでデータをコピーできます。これはAPI内部でデータを受け渡すための特別な処理が行われているからです。 したがって方法は二つあります。 一つ目はユーザー定義メッセージを使用するのを止めて、WM_SETTEXTとWM_COPYDATAを用いる方法。 二つ目はGlobalAddAtom等のプロセス間でメモリを共有するための仕組みを併用することです。 _________________ 甕星 <mikahosi@abox9.so-net.ne.jp> http://blogs.msmvp.jp/mikahosi/ | ||||||||||||
|
投稿日時: 2006-06-08 12:05
プロセス間で HGLOBAL を共有できるのは Win16 時代の話です。 Win32 以降では通用しません。 LPARAM, WPARAM (=実質 32bit 値)以上のユーザ定義データを送信する時は、独自定義のメッセージではなく、WM_COPYDATA メッセージを SendMessage() します。 | ||||||||||||
|
投稿日時: 2006-06-09 09:50
Hongliangさん、Elleさん、甕星さん、渋木宏明さん、ありがとうございます。
いろいろとアドバイスをいただいて、それを頼りに調べてみました。 WM_COPYDATAで試したところ、イベントは受信できているのですが、表示される文字は化けてしまっています。 まだ、作りが悪いのでしょうか?それとも何か型変換が間違っているのでしょうか? (基本的な事柄ですみません) ---------------サンプルの抜粋---------------------------------- [C#]送信側 struct COPYDATASTRUCT { public IntPtr dwData; public UInt32 cbData; public string lpData; } [DllImport("user32.dll", SetLastError = true)] private static extern uint SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref COPYDATASTRUCT lParam); //処理を行って送りたい情報(testTEST)をポストする COPYDATASTRUCT cs = new COPYDATASTRUCT(); string strTest = "testTEST"; cs.dwData = new IntPtr(0); cs.cbData = (uint)strTest.Length + 1; cs.lpData = strTest; SendMessage(HWND_BROADCAST, WM_COPYDATA, new IntPtr(0), ref cs); [C++]受信側 INT CALLBACK Proc(HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam) { case WM_COPYDATA: { COPYDATASTRUCT *pcs = (COPYDATASTRUCT*)lParam; //受け取った情報を目視するためにエディットボックスに表示 SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pcs->lpData); ::Beep(3000, 500); } } ---------------ここまで---------------------------------- | ||||||||||||
|
投稿日時: 2006-06-09 11:06
COPYDATASTRUCT の使いこなし?間違ってます。 COPYDATASTRUCT の定義は
です。 lpData メンバは char 型配列ではなく LPVOID 型であるため、lpData メンバに string 型をあてがっても、期待しているような動作は得られません。 このような場合は
のように、手動でマーシャリングして WM_COPYDATA メッセージを送信ます。 あと、WM_COPYDATA をブロードキャストしてはいけません。 どっかに「駄目だ」と書いてあるはずです。 | ||||||||||||
|
投稿日時: 2006-06-09 11:45
とっちゃんです。
あと、文字列を送る場合は、その文字コードの変換は送受信するアプリケーション間で取り決めしておく必要があります(もちろん、dwData部分も)。 WM_COPYDATA は、lpData から cbData 分のバイナリイメージをデッドコピーして送るので 対象は文字列に限っていませんからね。 >あと、WM_COPYDATA をブロードキャストしてはいけません。 >どっかに「駄目だ」と書いてあるはずです。 WM_COPYDATAのドキュメントの最後のほうに書かれています。 _________________ // とっちゃん(高萩 俊行)@わんくま同盟 // とっちゃん’Blog // MS-MVP for Developer Tools - Visual C++ // WindowsInstallerの話題はhttp://www.freeml.com/msiまで |