A recent project is to work with another company. It needs to receive the structure message sent by the other party, and then fill it in and send it back.
It involves transmitting and receiving struct through socket.
Generally, we only need to use the serialization and deserialization provided by C # To declare class/struct as serializable.
Then, use methods such as binaryformatter for serialization and deserialization ~ Google: C # serialization
However, if the other platform is C ++ or other non-. Net platforms, this will not work. Because of the differences between different platform types,
So there is no small trouble.
First, attach the type ing between C ++ and C:
C ++ Input and Output C #
========================================
Char CHR [255] O stringbuilder
Kca_dir I int
Lpcstr I string
Int I int
Lpstr o stringbuilder
Int * o out int
Dword I int
DWORD * o out int
Bool I bool
Rc_dbmgr I intptr
Long * o out long
| Data Type ing between APIs and C # |
| API data type |
Type description |
C # type |
API data type |
Type description |
C # type |
| Word |
16-bit unsigned integer |
Ushort |
Char |
Character |
Char |
| Long |
32-bit unsigned integer |
Int |
Dwordlong |
64-bit long integer |
Long |
| DWORD |
32-bit unsigned integer |
Uint |
HDC |
Device description table handle |
Int |
| Handle |
Handle, 32-bit integer |
Int |
Hgdiobj |
GDI object handle |
Int |
| Uint |
32-bit unsigned integer |
Uint |
Hinstance |
Instance handle |
Int |
| Bool |
32-bit Boolean integer |
Bool |
Hwm |
Window handle |
Int |
| Lpstr |
32-bit pointer to a character |
String |
Hparam |
32-bit message Parameters |
Int |
| Lpcstr |
32-bit pointer to a common character |
String |
Lparam |
32-bit message Parameters |
Int |
| Byte |
Bytes |
Byte |
Wparam |
32-bit message Parameters |
Int |
Wtypes. hIn |
Unmanaged CLanguage type |
Managed class name |
Description |
Handle |
Void * |
System. intptr |
32-bit |
Byte |
Unsigned char |
System. byte |
8-digit |
Short |
Short |
System. int16 |
16-bit |
Word |
Unsigned short |
System. uint16 |
16-bit |
Int |
Int |
System. int32 |
32-bit |
Uint |
Unsigned int |
System. uint32 |
32-bit |
Long |
Long |
System. int32 |
32-bit |
Bool |
Long |
System. int32 |
32-bit |
DWORD |
Unsigned long |
System. uint32 |
32-bit |
Ulong |
Unsigned long |
System. uint32 |
32-bit |
Char |
Char |
System. Char |
It is modified with ANSI. |
Lpstr |
Char * |
System. string or system. stringbuilder |
It is modified with ANSI. |
Lpcstr |
Const char * |
System. string or system. stringbuilder |
It is modified with ANSI. |
Lpwstr |
Wchar_t * |
System. string or system. stringbuilder |
Use Unicode. |
Lpcwstr |
Const wchar_t * |
System. string or system. stringbuilder |
Use Unicode. |
Float |
Float |
System. Single |
32-bit |
Double |
Double |
System. Double |
64-bit |
Note that the unmanaged bool corresponds to system. int32 in C. You can use bool directly when calling APIs.
The socket transmits byte []. Therefore, we need to convert struct to byte []. The following method is provided by someone else.
// Convert struct to byte []
Static byte [] structtobytes (Object structobj)
{
Int size = marshal. sizeof (structobj );
Intptr buffer = marshal. allochglobal (size );
Try
{
Marshal. structuretoptr (structobj, buffer, false );
Byte [] bytes = new byte [size];
Marshal. Copy (buffer, bytes, 0, size );
Return bytes;
}
Finally
{
Marshal. freehglobal (buffer );
}
}
// Byte [] to struct
Static object bytestostruct (byte [] bytes, type strcuttype)
{
Int size = marshal. sizeof (strcuttype );
Intptr buffer = marshal. allochglobal (size );
Try
{
Marshal. Copy (bytes, 0, buffer, size );
Return marshal. ptrtostructure (buffer, strcuttype );
}
Finally
{
Marshal. freehglobal (buffer );
}
}
Generally, this is the end. However, in addition to the basic data types int, long, and byte in struct, there are char *. For example:
typedef struct{ char szStatus[924]; char szError[196]; BYTE bEmergent;} CHECK_STATUS_PARAM
To ensure the correctness of data transmission and reading, the length of the string should be fixed.
This involves sending and processing strings. See: http://msdn.microsoft.com/zh-cn/library/s9ts558h (vs.80). aspx
In different cases, we need to use different sending options.
String used in the Structure
A string is a valid member of the structure. However, the stringbuilder buffer is invalid in the structure. The following table shows the options for sending a string when it is sent as a field. The financialasattribute attribute provides several unmanagedtype enumeration values to mail strings to fields.
Description of unmanaged formats of enumeration types
Unmanagedtype. BSTR
BSTR of the COM style with preset length and Unicode characters.
Unmanagedtype. lpstr
Pointer to the null ending array of ANSI characters.
Unmanagedtype. lptstr
Pointer to the null termination array of platform-related characters.
Unmanagedtype. lpwstr
Pointer to the null ending array of Unicode characters.
Unmanagedtype. byvaltstr
A fixed-length character array. the type of the array is determined by the character set containing the structure of the array.
The project requires ANSI encoding, so the stuct corresponding to C # is:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CHECK_STATUS_PARAM
{
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 924 )]
public string szStatus;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 196 )]
public string szError;
public byte bEmergent;
}
To ensure correctness, each member of the object is explicitly controlled in the precise position of the unmanaged memory. You can also use fieldoffsetattribute to indicate the position of the field in the type. This method is only used when layoutkind is set to explicit. .