如何将其转换为c#(编组)

时间:2011-04-07 03:30:59

标签: c# c++ interop marshalling

我有这些声明(DLL)并试图在C#中转换它,所以我可以从DLL调用函数。

struct1到struct3

相同
typedef struct1  
{  
    int num;  
    char chars[25];  
    short shrt;  
    union  
    {  
         struct4 objstruct4;  
    }  
}  

typedef struct
{        
    Long Length;    
    short Type;    
    union    
    {
       struct1 objStruct1;      
       struct2 objStruct2;      
       struct3 objStruct3;    
    }Data;  
} Msg;

在C#中,我将这些转换为struct1和struct3

相同
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct struct1  
{
    [MarshalAs(UnmanagedType.I4)]
    public Int32 num;  

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

    [MarshalAs(UnmanagedType.I2)]
    public short shrt;  

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct struct4
    {                
        [MarshalAs(UnmanagedType.Struct)]
        public ...
        ...
    }

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
protected struct Msg
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.I4)]
    public int Length;

    [FieldOffset(4)]
    [MarshalAs(UnmanagedType.I2)]
    public short Type;

    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.Struct)]
    public Data MsgData;  
}

[StructLayout(LayoutKind.Explicit, Pack = 1, CharSet = CharSet.Ansi)]
public struct Data
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.Struct)]
    public struct1 objStruct1;      

    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.Struct)]
    public struct2 objStruct2;      

    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.Struct)]
    public struct3 objStruct3;    

}

问题是当我尝试从DLL调用函数并将结构MSG作为REF传递时, 内部结构/联合(struct1到struct3)的某些成员变量没有值。 它就像在记忆中隆隆一样......

但是当我在struct MSG中删除struct1或struct2时,其余内部结构/联合中的所有成员变量都被成功检索。

如果我的转换是正确的,或者我错过了什么,我可以问你的建议吗? 或者有更好的方法来转换这个或你有答案为什么会出现这个问题。 我怀疑的一件事是结构的大小,ANSI或Unicode,以及变量,结构的排列。

请指教 - 谢谢。

样本2:
    ////////////////

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct struct1  
{
    [MarshalAs(UnmanagedType.I4)]
    public Int32 num1;  

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

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct struct2 
{
    [MarshalAs(UnmanagedType.I4)]
    public Int32 num2;  
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct struct3 
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = size + 1)]
    public string chars;

    [MarshalAs(UnmanagedType.I4)]
    public Int32 num3;  
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct struct4
{
    [MarshalAs(UnmanagedType.I4)]
    public Int32 num4;  

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

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
    public struct Data
    {
      //[FieldOffSet(0)]
      public struct1 str1;

      //[FieldOffSet(0)]
      public struct2 str2;

      //[FieldOffSet(0)]
      public struct3 str3;
    }
}
////////////////

1 个答案:

答案 0 :(得分:2)

没有明显的理由为什么你选择Pack = 1,大多数C编译器的默认值是8,就像.NET一样。偏移6处的MsgData是不确定的。在测试C程序中使用sizeof和offsetof()来找出所有内容的位置。在测试C#程序中与Marshal.SizeOf和OffsetOf()进行比较。在他们完全同意之前,这是行不通的。