我可以让一个字符串对象在结构中存储它的数据吗?

Can I have a string object store its data within the structure?

我正在寻找一种快速序列化由基本值类型和字符串组成的自定义结构的方法。

使用 C++CLI 固定结构实例和目标数组的指针,然后对数据进行 memcpy,对于所有值类型都非常有效。但是,如果我包含任何引用类型(例如字符串),那么我得到的只是引用地址。

预期如此,否则结构不可能具有固定的..结构。我想也许,如果我将字符串设置为固定大小,它可能会将它放在结构中。将 < VBFixedString(256) > 添加到字符串声明并没有实现这一点。

是否还有其他任何东西可以将实际数据放入结构中?

固定一个托管对象并对内容进行 memcpy 永远不会给你想要的东西。任何托管对象,无论是 String、字符数组还是其他任何对象都将显示为引用,您将只获得一个内存位置。

如果我从字里行间读到,听起来您需要调用一些 C 或 C++(不是 C++/CLI)代码,并向其传递一个类似于以下内容的 C 结构:

struct UnmanagedFoo
{
    int a_number;
    char a_string[256];
};

如果是这种情况,那么我会通过设置自动封送处理来为您处理来解决这个问题。以下是您如何定义该结构,以便它正确编组。 (我在这里使用 C# 语法,但它应该很容易转换为 VB.net 语法。)

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct ManagedFoo
{
    public int a_number;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
    public string a_string;
}

解释:

  • StructLayout(LayoutKind.Sequential) 指定字段应按声明的顺序排列。如果编译器需要,默认的 LayoutKind Auto 允许对字段重新排序。
  • CharSet=CharSet.Ansi specifies the type of strings to marshal. You can specify CharSet.Ansi to get char strings on the C++ side, or CharSet.Unicode 在 C++ 中得到 wchar_t 个字符串。
  • MarshalAs(UnmanagedType.ByValTStr) specifies a string inline to the struct, which is what you were asking about. There are several other string types, with different semantics, see the UnmanagedType MSDN 页面上的描述。
  • SizeConst=256指定字符数组的大小。请注意,这指定了字符数(或者在做数组时,数组元素的数量),不是字节数。

现在,这些编组属性是对 .Net 中内置编组器的指令,您可以直接从 VB.Net 代码中调用它。要使用它,请调用 Marshal.StructureToPtr to go from the .Net object to unmanaged memory, and Marshal.PtrToStructure 从非托管内存转到 .Net 对象。 MSDN 有一些调用这两种方法的好例子,看看链接的页面。

等等,C++/CLI 怎么样? 是的,您可以使用 C++/CLI 将 .Net 对象编组为 C 结构。如果您的结构变得太复杂而无法用 MarshalAs 属性表示,那么这样做非常合适。在这种情况下,您需要做的是:像我上面列出的那样声明您的 .Net 结构,不带 MarshalAsStructLayout。还要声明 C 结构,普通的和普通的,也如上所列。当你需要从一个切换到另一个时,复制东西一个字段一个字段,而不是一个大的memcpy。是的,所有基本类型(整数、双精度等)的字段都是重复的 output.a_number = input.a_number,但这是正确的做法。