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;
}
MAIN:
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没有值。
答案 0 :(得分:2)
代替MarshalAs[UnmanagedType.ByValArray]
,您应该在结构声明中使用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:
ByValTStr :用于在线, 固定长度的字符数组 出现在一个结构中。该 与ByValTStr一起使用的字符类型是 由...决定 System.Runtime.InteropServices.CharSet 的论点 System.Runtime.InteropServices.StructLayoutAttribute 适用于包含结构。 总是使用 MarshalAsAttribute.SizeConst字段 表示数组的大小。
.NET Framework ByValTStr类型的行为 像C风格的固定大小的字符串 在结构内部(例如,char S [5])。托管代码中的行为 与Microsoft Visual不同 基本6.0行为,不是null 终止(例如,MyString As 字符串* 5)。
'ByValArray'sais(强调我的)的文档:
设置MarshalAsAttribute.Value时 到ByValArray,SizeConst必须是 设置为表示元素的数量 在数组中。 ArraySubType字段 可以选择包含 数组元素的UnmanagedType 什么时候需要区分 在字符串类型中。你只能使用 这个UnmanagedType在一个数组上 在结构中显示为字段。
因此,我认为您的代码可以使用ByValArray
,您还应该在ArraySubType
属性中添加LPStr
MarshalAs
。