C # Calling c ++ dll files is a very troublesome task. The first problem is data type conversion, I believe that c # developers often forget the c ++ Basics of the school just like me (language features ).
There are a large number of conversion tables and a large number of conversion instances on the Internet, but they do not emphasize a more important issue, it is the correspondence between the c # data type and the memory size of the c ++ data type.
If the dll file contains only some basic types, this problem may be ignored, but if it is a combination type (this name may be inappropriate), such as struct and class types, whether the Statement of the length of the member variable is correct or not will determine your success or failure in calling the dll file.
The following code is not the source code of the dll file, but the c ++ example code provided by the vendor.
Struct statement in c ++
Typedef struct
{
Unsigned charPort;
Unsigned longId;
Unsigned charCtrl;
Unsigned charpData [8];
} HSCAN_MSG;
Function declaration in c ++ (one c ++ program references another c ++ dll file)
Extern "C" int _ stdcall HSCAN_SendCANMessage (unsigned char nDevice, unsigned char nPort, HSCAN_MSG * msg, int nLength );
Calls in c ++:
....
HSCAN_MSG msg [2, 100];
.....
HSCAN_SendCANMessage (m_nDevice, m_nPort, msg, nFrames );
The code above shows that msg is an array of struct.
Below is my c # code
C # struct Declaration: (declarative)
[StructLayout (LayoutKind. Sequential)]
Public struct HSCAN_MSG
{
// UnmanagedType. ByValArray, [financialas (UnmanagedType. U1)] This is very important, that is, to declare the corresponding type and length
[Financialas (UnmanagedType. U1)]
Public byte Port;
[Financialas (UnmanagedType. U4)]
Public uint nId;
[Financialas (UnmanagedType. U1)]
Public byte nCtrl;
[Financialas (UnmanagedType. ByValArray, SizeConst = 8)]
Public byte [] pData;
};
C # function declaration
[DllImport ("hs21_api. dll")]
Public static extern int HSCAN_SendCANMessage (
Byte nDevice, byte nPort, HSCAN_MSG [] pMsg, int nLength );
C # function call
HSCAN_MSG [] msg = new HSCAN_MSG [1]; // the size of the sending buffer can be set as needed;
For (int yy = 0; yy <msg. Length; yy ++)
{
Msg [yy] = new HSCAN_MSG ();
}
// The instantiation of members in the... struct is omitted.
HSCAN_SendCANMessage (0x0, 0x0, msg, 1)
Where struct and class can only be used as pointers
Struct statement in c ++
Typedef struct
{
Unsigned charPort;
Unsigned longId;
Unsigned charCtrl;
Unsigned charpData [8];
} HSCAN_MSG;
Function declaration in c ++ (one c ++ program references another c ++ dll file)
Extern "C" int _ stdcall HSCAN_SendCANMessage (unsigned char nDevice, unsigned char nPort, HSCAN_MSG * msg, int nLength );
Struct statement in c:
[StructLayout (LayoutKind. Sequential)]
Public struct HSCAN_MSG
{
[Financialas (UnmanagedType. U1)]
Public byte Port;
/// <Summary>
/// Node ID. When nEFF is set to 1 (Extended frame) and 29-bit nEFF = 0 (standard frame), the value is 11 bits;
/// </Summary>
[Financialas (UnmanagedType. U4)]
Public uint nId;
[Financialas (UnmanagedType. U1)]
Public byte nCtrl;
[Financialas (UnmanagedType. ByValArray, SizeConst = 8)]
Public byte [] pData;
};
C # function call: contains the method to use the pointer IntPtr to replace the struct array and read the 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" + "read 0 ports:" + count. ToString () + "frame data ";
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 receives 0 ports" + 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 ();
}