C#調用c++Dll結構體數組指標的問題

來源:互聯網
上載者:User

C#調用c++dll檔案是一件很麻煩的事情,首先面臨的是資料類型轉換的問題,相信經常做c#開發的都和我一樣把學校的那點c++底子都忘光了吧(語言屬性類別)。

網上有一大堆得轉換對應表,也有一大堆的轉換執行個體,但是都沒有強調一個更重要的問題,就是c#資料類型和c++資料類型占記憶體長度的對應關係。

如果dll檔案中只包含一些基礎類型,那這個問題可能可以被忽略,但是如果是組合類別型(這個叫法也許不妥),如結構體、類類型等,在其中的成員變數的長度的申明正確與否將決定你對dll檔案調用的成敗。

如有以下代碼,其實不是dll檔案的源碼,而是廠商給的c++例子代碼

c++中的結構體申明 

typedef struct

{

unsigned charPort;

unsigned longId;

unsigned charCtrl;

unsigned charpData[8];

}HSCAN_MSG;

c++中的函數申明(一個c++程式引用另一個c++的dll檔案)

extern "C" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength); 

c++中的調用:

....

HSCAN_MSG msg[100]; 

..... 

HSCAN_SendCANMessage(m_nDevice,m_nPort,msg,nFrames);

由上述代碼可見,msg是個結構體的數組。

下面是我的c#的代碼

c#結構體申明:(申明成) 

[StructLayout(LayoutKind.Sequential)]

        public struct  HSCAN_MSG

        {

    // UnmanagedType.ByValArray, [MarshalAs(UnmanagedType.U1)]這個非常重要,就是申明對應類型和長度的

            [MarshalAs(UnmanagedType.U1)]

            public byte Port;

            [MarshalAs(UnmanagedType.U4)]

            public uint nId;

            [MarshalAs(UnmanagedType.U1)]

            public byte nCtrl;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]

            public byte[] pData;

        }; 

 

 c#函數申明

[DllImport("HS2106API.dll")]

        public static extern int HSCAN_SendCANMessage(

             byte nDevice, byte nPort, HSCAN_MSG[] pMsg, int nLength); 

C#函數調用

 HSCAN_MSG[] msg = new HSCAN_MSG[1];//發送緩衝區大小可根據需要設定;

            for (int yy = 0; yy < msg.Length; yy++)

            {

                msg[yy] = new HSCAN_MSG();

            }

    //...結構體中的成員的執行個體化略

    HSCAN_SendCANMessage(0x0, 0x0, msg, 1) 

 

那些只能用指標不能用結構體和類的地方

 

 c++中的結構體申明 

typedef struct

{

unsigned charPort;

unsigned longId;

unsigned charCtrl;

unsigned charpData[8];

}HSCAN_MSG;

 c++中的函數申明(一個c++程式引用另一個c++的dll檔案)

extern "C" int _stdcall HSCAN_SendCANMessage(unsigned char nDevice,unsigned char nPort,HSCAN_MSG *msg,int nLength);

 

c#中的結構體申明:

[StructLayout(LayoutKind.Sequential)]

        public struct HSCAN_MSG

        {

            [MarshalAs(UnmanagedType.U1)]

            public byte Port;

            /// <summary>

            /// 節點標識,nEFF=1 時(擴充幀),為29 位nEFF=0(標準幀)時,為11 位;

            /// </summary>

            [MarshalAs(UnmanagedType.U4)]

            public uint nId;

            [MarshalAs(UnmanagedType.U1)]

            public byte nCtrl;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]

            public byte[] pData;

        }; 

 

c#函數的調用:包含使用指標IntPtr替代結構體數組和讀取IntPtr的方法

HSCAN_MSG[] msg1 = new HSCAN_MSG[10];

                for (int i = 0; i < msg1.Length; i++)

                {

                    msg1[i] = new HSCAN_MSG();

                    msg1[i].pData = new byte[8];

                }

                IntPtr[] ptArray = new IntPtr[1];

                ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)) * 10);

                IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(HSCAN_MSG)));

                Marshal.Copy(ptArray, 0, pt, 1); 

              

                int count = HSCAN_ReadCANMessage(0x0, 0,pt, 10);

                

                textBoxStatus.Text += "\r\n" + "讀取0口:" + count.ToString() + "幀資料";

                for (int j = 0; j < 10; j++)

                {

                    msg1[j] =

                        (HSCAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)pt+ j * Marshal.SizeOf(typeof(HSCAN_MSG)))

                        , typeof(HSCAN_MSG));

                    textBoxStatus.Text += "\r\n收到0口" + Convert.ToByte(msg1[j].pData[0]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[1]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[2]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[3]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[4]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[5]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[6]).ToString()

                        + "|" + Convert.ToByte(msg1[j].pData[7]).ToString();

                } 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.