【问题标题】:Export struct with 2 Array from C++ into C#将带有 2 个数组的结构从 C++ 导出到 C#
【发布时间】:2014-09-23 12:12:04
【问题描述】:

帮助

在 C++ 中

    #pragma pack(push,1) 
typedef struct SIGMPGroup{
  int temp;
  char name[50]; //name of group
  int port; 
  char addr[50]; //network address "229."
  //int ttl;          //
  //int loop;         // 0 - no loop back, 1 - loop back

  SIGMPGroup():
  temp(0),
  port(0)
  //ttl(-1),
  //loop(0)
  {}
};
#pragma pack(pop)

C#

public static SIGMPGroup DTIGMPGroup = new SIGMPGroup { temp = 56, name = "Example",port = 4000 };
   [StructLayout(LayoutKind.Explicit, Pack = 1, CharSet = CharSet.Ansi, Size = 108)]
   public struct SIGMPGroup{
     [FieldOffset(0)] 
     public int temp;
     [ FieldOffset(4), MarshalAs(UnmanagedType.ByValTStr,SizeConst=50)]
     public string name; //name of group
     [FieldOffset(54)]
     public int port;

     [FieldOffset(58), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
     public string addr;

   }

    [DllImport(Eth_DLL, CallingConvention = CallingConvention.Cdecl)]
    public static extern void Leave(ref SIGMPGroup data);

   ImportFunctionEth.Leave(ref ImportFunctionEth.DTIGMPGroup);

运行后出现错误: 无法从程序集“ConsoleApplication1,版本 = 1.0.0.0,文化 = 中性,PublicKeyToken = null”加载类型“SIGMPGroup”,因为它包含偏移 58 处的对象字段,该字段未正确对齐或重叠字段不代表对象。

如果代码

 [FieldOffset(58), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
 public string addr;

删除,一切正常。为什么?

只能这样工作

   [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
   public struct SIGMPGroup{

     public int temp;
     [  MarshalAs(UnmanagedType.ByValTStr,SizeConst=50)]
     public string name; //name of group

     public int port;

     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
     public string addr;

   }

【问题讨论】:

  • 似乎不允许未对齐字符串的标准编组。我会用 SizeConst = 108 声明这个结构中唯一的 byte[] 成员,并手动进行所有转换,例如,通过使用 BitConverter 类、String(sbyte*) 构造函数等。
  • 如果用作示例 [ FieldOffset(4), MarshalAs(UnmanagedType.ByValArray,SizeConst=50)] public char[] name;我有错误:无法打包类型,因为嵌入式数组实例的长度与布局中声明的长度不匹配。

标签: arrays string dllimport


【解决方案1】:

不太清楚这个错误是怎么回事,CLR 似乎出于某种神秘的原因想要保持结构 blittable。当然不是,字符串破坏了它。最终,错误是由 port 字段引起的,它违反了 .NET 内存模型的承诺,即 int 等简单类型的更新是原子的。它的偏移量被推到 56 并且与第二个字符串重叠。

StructLayout.Explicit 可能很古怪,但您的帮助很大。不帮忙就解决了:

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SIGMPGroup {
    public int temp;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string name; //name of group
    public int port;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string addr;
}

...
Debug.Assert(Marshal.SizeOf(typeof(SIGMPGroup) == 108);   // fine

【讨论】:

    猜你喜欢
    • 2019-08-18
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多