生活随笔
收集整理的這篇文章主要介紹了
c++与C# winform的消息通讯--(结构体与byte数组的使用)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉載:http://www.cnblogs.com/lizhaoduo/p/3870809.html
近期正在做一個藍牙驅動的使用程序,其中有一塊從c++發送數據到C#的部分,網上查了很多資料,大多都是介紹如何通過調用函數獲取用戶數據。并且在消息發送中,很少介紹如何發送一個結構體,并且結構體里面有
byte數組(硬件開發常用)等如何進行處理。
首先c++里面要建立一個dll文件:
1 BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,LPVOID lpReserved)2 {3 switch (ul_reason_for_call)4 {5 case DLL_PROCESS_ATTACH:6 case DLL_THREAD_ATTACH:7 case DLL_THREAD_DETACH:8 case DLL_PROCESS_DETACH:9 break;
10 }
11 return TRUE;
12 }
13
14 struct DevInfo//定義一個我自己的數據結構體
15 {
16 INT32 id;
17 char name[20];
18 char mac[25];
19 BYTE data[100];
20 };
21
22 extern "C" __declspec(dllexport) int sendTest(INT32 msg)//測試用的發布函數,這個int32參數一點作用都沒有
23 {
24 DevInfo *pinfo=new DevInfo();
25 pinfo->id=999;
26 sprintf(pinfo->name,"myDevice");
27 sprintf(pinfo->mac,"19:4x:3a:4a");
28
29 for (int i = 0; i < 100; i++)
30 {
31 pinfo->data[i]=(BYTE)(0x40+i);
32 }
33
34 COPYDATASTRUCT cpd; /*給COPYDATASTRUCT結構賦值,COPYDATASTRUCT,這個也是系統自己定義的*/
35 cpd.dwData = 959; //定義一個標示符(我這里沒有用到)
36 cpd.cbData = sizeof(DevInfo);
37 cpd.lpData = pinfo; //將指針的地址通過消息發送
38
39 HWND handle2=::FindWindowA(NULL,(LPCSTR)"Form1");//獲取窗口的句柄
40
41 ::SendMessageA(handle2,WM_COPYDATA,(WPARAM)13,(LPARAM)&cpd);
42
43 //這個地方必須要用sendMessageA,如果用post的話,則可能會出現數據還沒有發送完
44 //系統就把定義的DevInfo 給清理掉了
45
46 std::cout<<"發送數據消息"<<WM_COPYDATA<<std::endl;
47 delete pinfo;
48
49 return 12;
50 }
/*****************************************************************/
c#語言部分
1 namespace Test2 {3 public partial class Form1 : Form4 {5 public Form1()6 {7 InitializeComponent();8 }9
10 private const int WM_COPYDATA = 0x004A;//自己定義一個消息是必須的了
11
12 [DllImport("BlueTooth4.dll", EntryPoint = "sendTest", CallingConvention = CallingConvention.Cdecl)]
13 public static extern Int32 sendTest(int msg);//我們剛才執行的事件,這個是為了測試用才這樣做的
14
15
16 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
17 public struct COPYDATASTRUCT//定義數據傳輸的結構
18 {
19 public IntPtr dwData;
20 public int cbData;
21 public IntPtr lpData;
22 }
23
24 //定義要傳遞的Struct
25 [StructLayout(LayoutKind.Sequential)]//如果發現處理的數據有亂碼的話,則在此處加上 ,CharSet = CharSet.Ansi
26 struct dataInfo
27 {
28 public IntPtr id;
29
30 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
31 public string name;
32
33 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 25)]
34 public string mac;
35
36 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
37 public byte[] data;
38 }
39
40 protected override void DefWndProc(ref Message m)//開始處理消息
41 {
42 switch (m.Msg)
43 {
44 //接收CopyData消息,讀取發送過來的數據
45 case WM_COPYDATA:
46 COPYDATASTRUCT copydata = new COPYDATASTRUCT();
47 COPYDATASTRUCT RecvData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
48 dataInfo h = (dataInfo)Marshal.PtrToStructure((IntPtr)RecvData.lpData, typeof(dataInfo));//這句和上面的一句就已經將數據進行轉換了
49 break;
50 default:
51 base.DefWndProc(ref m);
52 break;
53 }
54
55 }
56 }
57 }
?
1、在這次處理的時候,在消息發送過來的數據遇到過是亂碼的情況,可能是字符串的編碼格式有問題( CharSet = CharSet.Ansi)也可能是長度定義的不夠 托管與非托管之間創建了一個數據塊,然后他將兩個數據塊進行對齊,然后將數據讀取出來轉變成我們想要的結構。
2、查過很多地方,好像在介紹c++post數據的時候,很少有介紹到用Byte數組的,而byte數組是在很多硬件設計(串口、usb)下使用比較多的 他的UnmanagedType應該是ByValArray
3、 ?? dataInfo h = (dataInfo)Marshal.PtrToStructure((IntPtr)RecvData.lpData, typeof(dataInfo));//這句和上面的一句就已經將數據進行轉換了 ?? 在這句上,我發現(IntPtr)RecvData.lpData,其實發送的就是pInfo的地址,當時想,我要是直接從dll發送給from不就可以了? ?? 結果測試了一下,不行,提示內存錯誤。應該是托管代碼與非托管代碼之間為了數據交互增加的一個接口,一般不允許繞過! ? ?估計有了這樣的數據傳輸方式,一般硬件的數據傳輸基本上就ok了,以后完全可以用c++寫驅動,寫底層接口,用c#做界面開發了!!
轉載于:https://www.cnblogs.com/y114113/p/6289784.html
總結
以上是生活随笔為你收集整理的c++与C# winform的消息通讯--(结构体与byte数组的使用)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。