【问题标题】:C# pinvoke marshaling unionsC# pinvoke 编组联合
【发布时间】:2014-11-19 02:24:50
【问题描述】:

我在将 C Union 转换为 C# 时遇到了一些问题。这是联盟的定义:

union Info
{
    char        varChar[8];
    short       varShort[4];
    int         varInteger[2];
    float       varFloat[2];
    double      varDouble;
    __int64     varInteger64;
    char        varSzText[8];   
};

这是我在 C# 中的尝试之一:

[StructLayout(LayoutKind.Explicit)]
public struct Info
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string varChar;

    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 4)]
    public short[] varShort;

    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I4, SizeConst = 2)]
    public int[] varInteger;

    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.R4, SizeConst = 2)]
    public float[] varFloat;

    [FieldOffset(0)]
    public double varDouble;

    [FieldOffset(0)]
    public long varInteger64;

    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 8)]    //LPStr, LPWStr, BStr oder LPTStr 
    public string[] varSzText;
};

我可能在这里做错了。我读了一些关于引用和值类型的东西,它们在内存布局中的处理方式不同。由于这里的大多数字段都是数组,我猜,这些都是值类型。这意味着它们并不都在 [FieldOffset(0)]?

另一个令人头疼的是最后一个字段varSzText。 我得到了一个使用该字段的示例 C/C++ 程序,如下所示: printf("Text: %s\n", &info.varSzText[0]); 我的 C 不是很好,但如果我的解释是正确的,那么 char varSzText[8]; 将地址存储到 (\0-terminated) 字符串。示例程序打印至少一个 20 多长的字符串。

  • 谁能告诉我,如何组织这个联盟?
  • 我在发帖前用谷歌搜索并搜索了论坛,但大多数情况下我发现了具有简单类型(没有数组/字符串)的非常简单的联合。有人知道有关 pinvoke/marshaling 的好书吗?

编辑: 我发现,联合仅在具有类型字段的结构中使用,它可以提示我实际存储在联合中的内容。因此,我会坚持使用 Deduplicator 的回答。我将为每个字段创建不同的结构并根据类型字段解析联合。

【问题讨论】:

  • 我删除了你的先发制人的道歉和你的名字 - 所以认为这些是不必要的,它们只会给你的问题增加噪音。不过不用担心 - 对于初次使用的用户来说,这是一个精心设计的问题。
  • 如果我是你,我会为此创建一个结构。在结构中,我有一个 byte[] 编组为长度为 8 的 by val 数组。然后我会为各种类型添加 getter 和 setter。

标签: c# pinvoke marshalling


【解决方案1】:

您的问题是union 可以是很多东西,程序员在任何给定时刻决定它是什么(最好不要搞砸)。
由于没有标记,因此没有固有的决定方式。

所以,要走的路是:

  1. 决定它是什么选项。
  2. 据此进行马歇尔。

(您可能希望使用 C++/CLI 包装器来替代更有趣的情况下的灵活性。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 2012-04-05
    • 2014-11-04
    • 1970-01-01
    相关资源
    最近更新 更多