将C结构体从DLL转换为C#

3

我正在使用一个用c语言编写的dll。我已经将所有我需要的函数导入到我的C#程序中。大多数函数我都能够正常工作,但是有几个函数我遇到了问题。我遇到问题的函数需要一个结构体作为输入。我认为我需要在C#中定义这个结构体,我已经尝试过了,但是我开始感到困惑,所以我会把我尝试过的东西留出来。这个结构体相当长,所以我会简单地介绍一下它在c语言中的样子:

typedef struct chain_link_info
{
  unsigned short command;
  unsigned long* buff_id;
  FLAGS_TYPES    flags;  // this is a union that i will list below
} CHAIN_LINK_INFO;

typedef union flags_type
{
  unsigned long ulong;

  struct
  {
    unsigned short std_flags;
    unsigned short high
  } ushort;

  struct
  {
    unsigned int a : 1;
    unsinged int b : 1;
    unsinged int c : 1;
    unsinged int d : 1;
    unsinged int e : 2;
    unsinged int f : 1;
    unsinged int g : 1;
    unsinged int h : 1;
    unsinged int i : 1;
    unsinged int j : 1;
    unsinged int k : 1;
    unsinged int l : 1;
    unsinged int m : 1;
    unsinged int n : 1;
    unsinged int o : 1;
    unsigned int high_word :16
  } std_bits;
} FLAGS_TYPE;

什么是在C#中定义这些结构的正确方式?谢谢。

1
我相信这是一个需要使用StructLayout的情况,但不能确定。 - Brad Christie
抱歉给你点了踩,我已经取消了。可能是误触了。我想知道这个联合体应该如何映射。 - Chris Pitman
3个回答

1
创建一个C#结构体,对其应用[StructLayout],并按照C语言中的相同顺序列出字段。对于FLAGS_TYPE结构体,必须在字段上使用[FieldOffset]属性。联合体的所有成员都从相同的内存地址开始,因此将它们应用相同的[FieldOffset(0)]。

更新:现在已经格式化了,我认为您根本不需要使用联合体。使用单个32位整数,并通过位运算获取不同的字段,这样更安全。


是的,问题应该是“在C语言中定义结构的正确方式是什么?”;-) - David Heffernan

1

这个 C 声明是无效的,所以很难给出一个好的答案。通常情况下你不能处理二进制位域(bit fields),但在这种特殊情况下,它可以工作,因为它们都是 8 位的倍数。你需要 [StructLayout(LayoutKind.Explicit)] 并且对每个字段使用 [FieldOffset(x)]。坏命名的 unsigned long、std_flags 和 a 在偏移量 0 处。b 在偏移量 1 处。high 和 high_word 在偏移量 2 处。


非常抱歉,我已经更正了问题,使其更像实际的结构体。原始的结构体相当大,所以我只是试图将它们缩小,希望一个简单的答案能帮助我看到我做错了什么。谢谢。 - poco
好的,位域不再是8的倍数了。如果您想获取/设置单个位,您将需要使用&和|运算符。 - Hans Passant

0

FieldOffset 是以字节为单位的。因此,您只能通过 FieldOffset 表达到字节级别。 您可以创建自己的 FieldOffset


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接