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