如何从C++;到C#

如何从C++;到C#,c#,c++,struct,migration,C#,C++,Struct,Migration,我正在编写一个UDP客户端,它正在接收复杂的数据结构。 我确实有C++中的结构,但是我的程序是C<< /p> 比特域和并集有很多不同的结构 有没有什么方法不必手动转换结构 还有一种在C#中实现位字段和并集的简单方法吗 现在我正在使用位字段的属性,但这是一项困难的工作,很有可能出错 我提供了一个我现在正在做的简化示例,大约有50个结构,每个结构有100行代码 c++示例: typedef struct Message_s { unsigned char var : 2; unsig

我正在编写一个UDP客户端,它正在接收复杂的数据结构。 我确实有C++中的结构,但是我的程序是C<< /p> 比特域和并集有很多不同的结构

有没有什么方法不必手动转换结构

还有一种在C#中实现位字段和并集的简单方法吗

现在我正在使用位字段的属性,但这是一项困难的工作,很有可能出错

我提供了一个我现在正在做的简化示例,大约有50个结构,每个结构有100行代码

c++示例:

typedef struct Message_s
{
    unsigned char var : 2;
    unsigned char var2 : 6;

    union
    {
         struct
         {
            unsigned char sVar;
            unsigned char sVar2;
         }
         char arr[32];
     }    
}Message_t;
示例C#:

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
结构消息
{
专用字节字段1
公共字节变量
{
得到
{
返回(字节)(字段1和0x03);
}
设置
{
Field1=(字节)((Field1&~0x03)|值);
}
公共字节var2
{
得到
{
返回(字节)(字段1和0xFC);
}
设置
{

Field1=(字节)((Field1和0x03)值

简短的答案是否定的,似乎没有一种简单的方法将C++结构变成一个C格式。但是,有一种在C结构中做联合的方法;这是一个好主意,还是从类开始从头开始更好,取决于你。 要在C#结构中获取联合,请使用

LayoutKind.Explicit
FieldOffset
属性:

[StructLayout(LayoutKind.Explicit)]
struct StructTest
{
    // A byte at the beginning of the struct.
    [FieldOffset(0)]
    public byte byte1;

    // Another byte immediately after it.
    [FieldOffset(1)]
    public byte byte2;

    // Now an integer which covers both.
    [FieldOffset(0)]
    public Int16 int1;
}
您可以按照预期的方式使用此选项:

        var foo = new StructTest();
        foo.byte1 = 3;
        foo.byte2 = 6;
        Console.WriteLine("{0}", foo.int1);

        var bar = new StructTest();
        bar.int1 = 5050;
        Console.WriteLine("{0}, {1}", bar.byte1, bar.byte2);
生成
1539
186,19

这使您获得了联合结构,但它仍然不能解决位字段的主要问题。在这方面似乎没有达成共识(当然,除了您已经完成的工作;例如,请参见[])也许可以用 MsHalalas[/Cuth]属性做一些聪明的事情来把一个自定义的BITFER类映射到底层结构上,但是在这样的努力下,像你一样一直写自定义类可能更容易。有一些打字。在VS C++项目中,创建非托管结构:

struct Date_s
{
    union
    {
        struct
        {
            unsigned nWeekDay  : 3;    // 0..7   (3 bits)
            unsigned nMonthDay : 6;    // 0..31  (6 bits)
            unsigned           : 0;    // Force alignment to next boundary.
            unsigned nMonth    : 5;    // 0..12  (5 bits)
            unsigned nYear     : 8;    // 0..100 (8 bits)
        };
        unsigned bob;
    };
};
现在,我们创建一个封装此结构的托管类型:

public ref struct Date_ms
{
    AutoPtr<Date_s> data;
    Date_ms()
    {
        data = new Date_s();
    }

    property unsigned nWeekDay
    {
        unsigned get() { return data->nWeekDay; }
        void set(unsigned value) { data->nWeekDay = value; }
    }
    property unsigned nMonthDay
    {
        unsigned get() { return data->nMonthDay; }
        void set(unsigned value) { data->nMonthDay = value; }
    }
    property unsigned nMonth
    {
        unsigned get() { return data->nMonth; }
        void set(unsigned value) { data->nMonth = value; }
    }
    property unsigned nYear
    {
        unsigned get() { return data->nYear; }
        void set(unsigned value) { data->nYear = value; }
    }
    property unsigned bob
    {
        unsigned get() { return data->bob; }
        void set(unsigned value) { data->bob = value; }
    }
};
结果为
3,28,98
224

大巨人警告
像这样混合托管和非托管代码是危险的,这就是为什么Kerr首先编写AutoPtr的原因(顺便说一句,他关于这个主题的文章非常值得一读)。这对我来说是可行的,但我不能保证它不会导致内存泄漏。在部署它之前,你应该明确检查它是否按预期工作。

关于操作位字段,你可能需要查看System.Collections.Specialized.BitVector32。此外,根据你正在做的事情,你可能需要查看使用应用程序的枚举RoopLead宽度和标志的属性。这样写:我写了一个有规则的C++ DLL,它使所有的结构都不协调,这使我能够从C++中访问它们,不是吗?还有,另外一个问题,C++编译器是否保持了结构的字节和位顺序?不幸的是,ChristianElsner,我有同样的想法。似乎不起作用。这些结构是编译的,但它们的成员不能从C++中访问。通过使用<代码>结构> <代码> > <代码>值类< /C> >,使它成为托管结构,但然后,您会得到对位字段和联合的编译器错误。
public ref struct Date_ms
{
    AutoPtr<Date_s> data;
    Date_ms()
    {
        data = new Date_s();
    }

    property unsigned nWeekDay
    {
        unsigned get() { return data->nWeekDay; }
        void set(unsigned value) { data->nWeekDay = value; }
    }
    property unsigned nMonthDay
    {
        unsigned get() { return data->nMonthDay; }
        void set(unsigned value) { data->nMonthDay = value; }
    }
    property unsigned nMonth
    {
        unsigned get() { return data->nMonth; }
        void set(unsigned value) { data->nMonth = value; }
    }
    property unsigned nYear
    {
        unsigned get() { return data->nYear; }
        void set(unsigned value) { data->nYear = value; }
    }
    property unsigned bob
    {
        unsigned get() { return data->bob; }
        void set(unsigned value) { data->bob = value; }
    }
};
var test = new Date_ms();
test.nMonth = 3;
test.nMonthDay = 28;
test.nYear = 98;
Console.WriteLine("{0}, {1}, {2}", test.nMonth, test.nMonthDay, test.nYear);
Console.WriteLine("{0}", test.bob);