如何正确地将这些转换为c#,marshall,以便将这些结构传递给DLL(c+;+;)?

如何正确地将这些转换为c#,marshall,以便将这些结构传递给DLL(c+;+;)?,c#,c++,interop,marshalling,C#,C++,Interop,Marshalling,C++ C#: 主要内容: 问题: 只有MsgId和DataData_FldSizeAdmin具有相同的值。 我认为这是因为它们共享相同的内存地址 未知、SENDTIME和ReceiptTime没有值。在结构声明中应使用MashalAs[UnmanagedType.ByValtString]而不是MarshalAs[UnmanagedType.ByValtString]: 例如: AdminData oAdminData = new AdminData(); oAdminData.AdminD

C++

C#:

主要内容:

问题:

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


未知、SENDTIME和ReceiptTime没有值。

在结构声明中应使用
MashalAs[UnmanagedType.ByValtString]
而不是
MarshalAs[UnmanagedType.ByValtString]

例如:

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);
见:

ByValTStr:用于串联, 固定长度的字符数组 出现在一个结构中。这个 ByValTStr使用的字符类型为 由 System.Runtime.InteropServices.CharSet 政府的论据 System.Runtime.InteropServices.StructLayoutAttribute 应用于包含结构。 始终使用 MarshalAsAttribute.SizeConst字段 指示数组的大小

.NET Framework ByValTStr类型的行为 与C样式一样,固定大小的字符串 结构内部(例如,char s[5])。托管代码中的行为 与Microsoft Visual Studio不同 基本6.0行为,不为空 终止(例如,MyString As 字符串*5)

“ByValArray”sais(重点矿山)的文件:

设置MarshalAsAttribute.Value时 要创建ByValArray,SizeConst必须为 设置以指示元素的数量 在数组中数组子类型字段 可以选择包含 数组元素的非托管类型 什么时候需要区分 在字符串类型中。你只能使用 此非托管类型位于 在结构中显示为字段。


因此,我认为要使您的代码使用
ByValArray
,您还应该在
Marshallas
属性中添加
ArraySubType

我在c中尝试过这些,但我相信仍然缺少。。。对于内部结构的两个成员变量,我使用[FieldOffice(0)],因为它是C++中的一个联合。您是否在同一平台上保存和加载数据?你必须小心在不同的平台上寻找不同的路线。谢谢史蒂夫!是的!我在WinXP上运行这个。Steve你说的对齐是什么意思?抱歉,我还是c#的新手。当对c#struct进行封送处理时,它会生成一个字节块。字节数组中C#struct的每个成员在不同平台上的位置可能不同,因此有时需要调整编组生成字节数组的方式,使其在两个平台上的工作方式相同。@Ryan:btw,您可以在这里接受关于堆栈溢出的答案。。。甚至投票也是可能的;-)
    [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);
...
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;
}
...