c++與C# winform的消息通訊--(結構體與byte數組的使用)


 

近期正在做一個藍牙驅動的使用程序,其中有一塊從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 Test
 2 {
 3     public partial class Form1 : Form
 4     {
 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#做界面開發了!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM