C++

#define FIELD_SIZE_MSGID       24
#define FIELD_SIZE_TIME        12
#define FIELD_SIZE_ADMIN      256


typedef struct

{

      char MsgId[FIELD_SIZE_MSGID+1];

      char SendTime[FIELD_SIZE_TIME+1];

      char ReceiptTime[FIELD_SIZE_TIME+1];

} AdminDataM0;





typedef struct

{

      int Type;

      union

      {
         AdminDataM0 M0;
         char Data[FIELD_SIZE_ADMIN + 1];

      } AdData;


      char Unknown[FIELD_SIZE_ADMIN + 1];


} AdminData;

C#:
    [DllImport("Receiver.dll",
        CallingConvention = CallingConvention.Cdecl,
        ExactSpelling = false,
        SetLastError = false,
        CharSet = CharSet.Ansi,
        EntryPoint = "SendMessage")]
    [return: MarshalAs(UnmanagedType.I4)]
    protected static extern int SendMessage(
        [MarshalAs(UnmanagedType.Struct)] ref AdminData ptrAdminData,
);


   protected const Int32 FIELD_SIZE_MSGID = 24;
   protected const Int32 FIELD_SIZE_TIME = 12;
   protected const Int32 FIELD_SIZE_ADMIN = 256;

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct AdminDataM0
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = FIELD_SIZE_MSGID + 1)]
        public char[] MsgId;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = FIELD_SIZE_TIME + 1)]
        public char[] SendTime;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = FIELD_SIZE_TIME + 1)]
        public char[] ReceiptTime;
    }

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
 protected struct AdminData
{
     [MarshalAs(UnmanagedType.I4)]
     public Int32 nType;

     [MarshalAs(UnmanagedType.Struct)]
     public Data AdminData_Data;

     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
     public struct Data
     {
         [FieldOffset(0)]
         [MarshalAs(UnmanagedType.Struct)]
         public AdminDataM0 M0; //135

         [FieldOffset(0)]
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = FIELD_SIZE_ADMIN + 1)]
         public char[] Data_FldSizeAdmin;
     }

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = FIELD_SIZE_ADMIN + 1)]
     public char[] Unknown;
 }

主要:
AdminData oAdminData = new AdminData();
oAdminData.AdminData_Data = new oAdminData.Data();
oAdminData.AdminData_Data.M0 = new oAdminDataM0();

oAdminData.AdminData_Data.M0.MsgId = new char[FIELD_SIZE_MSGID + 1];
oAdminData.AdminData_Data.M0.SendTime = new char[FIELD_SIZE_TIME + 1];
oAdminData.AdminData_Data.M0.ReceiptTime = new char[FIELD_SIZE_TIME + 1];
oAdminData.AdminData_Data.Data_FldSizeAdmin = new char[FIELD_SIZE_ADMIN + 1];
oAdminData.Unknown = new char[FIELD_SIZE_ADMIN + 1];

string M0_MsgId = "MsgId";
string M0_SendTime = "Send Time";
string M0_ReceiptTime = "ReceiptTime";
string unknown =  "Unknown";

M0_MsgId.ToCharArray().CopyTo(oAdminData.AdminData_Data.M0.MsgId, 0);
M0_SendTime.ToCharArray().CopyTo(oAdminData.AdminData_Data.M0.SendTime, 0);
M0_ReceiptTime.ToCharArray().CopyTo(oAdminData.AdminData_Data.M0.ReceiptTime, 0);


// function to DLL

SendMessage(ref oAdminData);

问题:

只有MsgId和DataData_FldSizeAdmin具有相同的值。
我认为这是因为它们共享相同的内存地址。

UNKNOWN,SENDTIME和RECEIPTIME没有值。

最佳答案

代替MarshalAs[UnmanagedType.ByValArray],您应该在struct声明内使用MashalAs[UnmanagedType.ByValTStr]:

如:

...
public struct AdminDataM0
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FIELD_SIZE_MSGID + 1)]
    public string MsgId;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FIELD_SIZE_TIME + 1)]
    public string SendTime;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = FIELD_SIZE_TIME + 1)]
    public string ReceiptTime;
}
...

参见documentation:



“ByValArray” sais(强调我的)的文档:



因此,为了使您的代码可以使用ByValArray起作用,您还应该在ArraySubType属性中添加LPStrMarshalAs

08-28 21:37