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

发布于 2024-10-30 18:05:51 字数 3250 浏览 4 评论 0原文

我有这些声明 (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 调用函数并将 struct 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;
    }
}
////////////////

I have these declarations (DLL) and tried to convert it in C# so i can call the functions from the DLL.

Same for struct1 to 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;

In C#, i converted these...same for struct1 to 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;    

}

Problem is when I tried to call a function from the DLL and passed the struct MSG as REF,
some member variables of the inner structs/union (struct1 to struct3) don't have values.
Its like they are rumbled inside the memory...

But when I remove the struct1 or struct2 in struct MSG, all of the member variables inside the remaining inner structs/union were successfully retrieved.

Can I ask your advice if my conversion is correct or did i missed something...
Or is there a better way to convert this or you have answers why this problem occur.
One thing that I suspect is the size of the struct, ANSI or Unicode, and the arrangement of the variables, structs.

Please advise - thanks.

sample 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;
    }
}
////////////////

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红颜悴 2024-11-06 18:05:51

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

There's no obvious reason why you chose Pack=1, the default for most C compilers is 8, just like .NET. MsgData at offset 6 is iffy. Use sizeof and offsetof() in a test C program to find out where everything is located. Compare with Marshal.SizeOf and OffsetOf() in a test C# program. This isn't going to work until they agree exactly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文