【问题标题】:Moving structure data in C#在 C# 中移动结构数据
【发布时间】:2013-04-26 02:09:35
【问题描述】:

假设我在 C 中有以下结构

typedef struct
{
    int field1;
    char field2[16];
} MYSTRUCT;

现在我有一个用指向 MYSTRUCT 的指针调用的 C 例程,我需要填充结构,例如,

int MyCall(MYSTRUCT *ms)
{
    char *hello = "hello world";
    int hlen = strlen(hello);
    ms->field1 = hlen;
    strcpy_s(ms->field2,16,hello);
    return(hlen);
}

如何用 C# 编写 MyCall?我在 Visual Studio 2010 中试过这个:

...
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
public struct MYSTRUCT
{
    [FieldOffset(0)]
    UInt32 field1;
    [FieldOffset(4)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    string field2;
}

public int MyProc(ref MYSTRUCT ms)
{
    string hello = "hello world";
    int hlen = hello.Length;
    Marshal.Copy(hello, ms.field2, 0, hlen); // doesn't work
    Array.Copy(hello, ms.field2, hlen);      // doesn't work
    // tried a number of other ways with no luck
    // ms.field2 is not a resolved reference
    return(hlen);
}

感谢有关正确方法的任何提示。

【问题讨论】:

  • ms.field2=hello;,但您可能正在寻找其他东西。显示调用 MyProc 的代码可能有用...
  • 我还注意到您在 C 中的结构是 int 类型而不是 unsigned int,因此在 C# 中您可能希望将数据类型设为 Int32 而不是 UInt32
  • 其次,如果您将程序移植到 C#,则不必使用结构布局,如果您要通过引用传递结构,您不妨将其设为类,因为它通过引用传递。然后,您可以根据需要分配您的值。现在,如果您的函数被导出到动态库,那么您可以使用结构化布局做得很好。
  • 当您在 C# 中使用 Marshal 或 Array 副本时,您不需要做任何特别的事情。在您使用完结构并需要将其发送回非托管方法后,只需将其传递给 p/invoked 调用,内置的编组将完成所有工作。与从 p/invoked 方法返回结构相同 - 如果您正确定义结构,.NET 将为您完成编组工作。
  • 除非我在这里完全脱离了球并且你根本没有在本机代码之间编组......我假设你正在用你所有的编组东西做......在这种情况下,只是像使用 C# 中的任何其他类一样使用它:)

标签: c# windows visual-studio-2010


【解决方案1】:

尝试更改 StructLayout。

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct MYSTRUCT
{
    public UInt32 field1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string field2;
}

既然您作为参考传递,您是否尝试将其设置为:

public int MyProc(ref MYSTRUCT ms)
{
    string hello = "hello world";
    ms.field2 = hello;
    return hello.Length;
}

当使用ref 关键字时,你会像这样调用MyProc

static void Main(string[] args)
{
    var s = new MYSTRUCT();
    Console.WriteLine(MyProc(ref s)); // you must use "ref" when passing an argument
    Console.WriteLine(s.field2);
    Console.ReadKey();
}

【讨论】:

  • 谢谢!尽管显然我必须指定“公共字符串字段2”,即使 MYSTRUCT 是公共的。否则由于保护级别而无法访问。
  • 我越来越近了,但它似乎不喜欢“ref MYSTRUCT”。我假设这告诉 C# 它正在接收指向结构的指针,对吗?如果不是,那么声明它的正确方法是什么?
  • @Neilw,是的,“ref”关键字是指向结构的指针。你怎么称呼我的教授?你有什么错误吗?
猜你喜欢
  • 2020-05-15
  • 2015-09-19
  • 2015-10-07
  • 2023-03-16
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-01
相关资源
最近更新 更多