【问题标题】:C#: Convert List of simple structs to byte[]C#:将简单结构列表转换为 byte[]
【发布时间】:2010-11-05 15:27:25
【问题描述】:

在 C# 4.0 中,假设我有

List<HSZPAIR> myList

包含三个元素,其中 HSZPAIR 结构由以下方式定义:

[StructLayout(LayoutKind.Sequential)]
public struct HSZPAIR
{
    public IntPtr hszSvc;
    public IntPtr hszTopic;
}

如何为整个 myList 创建一个字节数组?在 C++ 中,您可以将结构数组转换为字节数组。我不确定如何在 C# 中做到这一点。

我在 DDEML 库中使用了一个旧的 Windows API 函数,它需要一个字节数组和数组中的元素数作为参数。如果您对更多背景感兴趣,API 功能是:

[DllImport("user32.dll", EntryPoint="DdeCreateDataHandle", CharSet=CharSet.Ansi)]
    public static extern IntPtr DdeCreateDataHandle(int idInst, byte[] pSrc, int cb, int cbOff, IntPtr hszItem, int wFmt, int afCmd);

Here is it's documentation on MSDN。 pSrc 参数是 HSZPAIR 结构的字节数组。数组的大小是 cb 参数。

【问题讨论】:

标签: c# list struct byte marshalling


【解决方案1】:

将结构转换为字节数组有点痛苦。你必须自己序列化它。但这可能没有必要。

鉴于您的清单:

List<HSZPAIR> myList;

可以通过调用ToArray获取数组:

HSZPAIR[] myArray = myList.ToArray();

现在,更改您的托管原型,使其采用 HSZPAIR[] 而不是 byte[]

public static extern IntPtr DdeCreateDataHandle(
    int idInst, HSZPAIR[] pSrc, int cb, int cbOff, IntPtr hszItem, int wFmt, int afCmd);

应该可以。毕竟,正如您所指出的,HSZPAIR 的数组实际上只是一个字节数组。

【讨论】:

  • 我喜欢这个想法,但 DdeCreateDataHandle 函数是一种通用函数,旨在将多种类型的数据数组转换为指针,以供其他 DDE 函数使用。如果我更改声明,那么它可能会破坏那些其他用法。采用 DdeCreateDataHandle 创建的 IntPtr 的函数应该知道数据是什么类型的结构。
  • 另外,我还没有足够的声望给你点赞,但我会回来给你点赞的。
  • @dmjones:您可能会在msdn.microsoft.com/en-us/library/aa719546(v=VS.71).aspx 的阵列封送样本中找到您要查找的内容。看起来页面已损坏,因为 C# 示例与 VB 示例混合在一起。但他们在那里展示了如何以几种不同的方式编组数组。
  • 另外,您可以为DdeCreateDataHandle 创建多个原型,只需将它们命名不同。例如DdeCreateDataHandleHSZPAIR 等。我不一定会推荐它作为通用解决方案,但它应该可以让您知道您是否能够调用该方法。
  • @Jim 我会看看你为编组数组提供的网络链接,但是重载 extern 原型的想法看起来很有效!非常感谢您花时间回答!
【解决方案2】:

我认为你可以使用 Marshal.StructureToPtr。

static byte[] StructureToByteArray(object obj)
{
   int length = Marshal.SizeOf(obj);
   byte[] data = new byte[length];
   IntPtr ptr = Marshal.AllocHGlobal(length);
   Marshal.StructureToPtr(obj, ptr, true);
   Marshal.Copy(ptr, data, 0, length);
   Marshal.FreeHGlobal(ptr);
   return data;
}

至于列表本身,它必须单独序列化。

【讨论】:

  • 这与我在原始帖子中的 Mastering Structs in C# 链接中使用的用于编组单个结构的内容非常相似。不过,我相信其他人会欣赏这些信息。
【解决方案3】:

我相信您需要在 extern 声明中将 pSrc 的类型定义为 IntPtr,而不是 byte[]。

【讨论】:

  • 查看您的评论后,我确实通过 google 看到其他人已经使用 IntPtr 或 byte[] 定义了 extern 定义。但我不确定如何使用 IntPtr 而不是 byte[] 让我更接近于传递这个结构数组。 (另外,我还没有足够的声望给你点赞,但我会回来给你点赞的)。
  • @dmjones:IntPtr 在 C# 中有一点“特权状态”;基本上,它“正常工作”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
相关资源
最近更新 更多