C++ 联合到 C# 工人阶级

c++ union to C# working class

本文关键字:工人阶级 C++      更新时间:2023-10-16

我只了解C++工会是如何运作的。 我认为我在 c# 类中复制的第一个注释块mac_const(如果没有,请解释原因( 我目前并不担心效率,只是担心它工作正常。 第二个评论块我什至不知道从哪里开始如何翻译它。 我不知道数据[2]映射到哪里,有人可以

//union {
//    unsigned short wd[4];
//    double data;
//    __int64 data64;
//}
//dbl_cnvt;
public class mac_const
{
byte[] basedata = new byte[8];
//public ushort[] wd
public ushort this[byte index]
{
get { return BitConverter.ToUInt16(basedata, index * 2); }
set { Array.Copy(BitConverter.GetBytes(value), 0, basedata, index * 2, 2); }
}
public double data
{
get { return BitConverter.ToDouble(basedata, 0); }
set { basedata = BitConverter.GetBytes(value); }
}
public long data64
{
get { return BitConverter.ToInt64(basedata, 0); }
set { basedata = BitConverter.GetBytes(value); }
}
}

//union {
//    unsigned short cmd[4];
//    unsigned long data[2];
//    __int64 data64;
//}
//data_conversion;
public class data_conversion_csharp
{
byte[] basedata = new byte[8];
// the c++ class only 
//public ushort[] cmd
public ushort this[byte index]
{
get { return BitConverter.ToUInt16(basedata, index * 2); }
set { Array.Copy(BitConverter.GetBytes(value), 0, basedata, index * 2, 2); }
}
public long[] data
{
// not sure what the mapping would be here, or if this should be data1 and data2 instead of an array
???
}
public long data64
{
???
}
}

编辑 - 关于工会必要性的解释 @ffhighwind 我试图移植一些C++代码,这些代码使联合按应有的方式使用。 我不明白数据中第二个长长的映射是如何发生的

lng_cnvt.data64 = (dbl_cnvt.data64 >> 6) + (long)0x400000000000; 
if (data < 0)
{
lng_cnvt.data64 = -lng_cnvt.data64;
lng_cnvt.cmd[3] = 0;
if (lng_cnvt.data64 == (__int64)0xC00000000000)
{
lng_cnvt.data64 = (__int64)0x800000000000; 
exp -= 1;
}
}
lng_cnvt.cmd[0] = (Ushort)((lng_cnvt.cmd[0] & 0xF000) | exp);
*ldata++ = lng_cnvt.ldata[0] & 0xFFFFFFL;
*ldata++ = ((lng_cnvt.data[0] >> 24) & 0x000FFL) |                                          
((lng_cnvt.data[1] << 8) & 0x0FFFF00L);

我没有投反对票,但没有 50+ 代表我无法发表评论,所以也许其他人在同一条船上。这样做的目的是什么,为什么你不能直接投反对?

也许您希望限制对象可以包含的类型。如果是这样,这能行吗?

class MyUnion
{
object obj;
MyUnion(SomeType o) { obj = o; }
//... constructors for all accepted Types
public object Value { get { return obj; } }
}

C# 是托管的,因此您不能真正期望对数据进行微调的低级别控件。如果你想要像C++这样的微调控制,你将需要 sizeof 和非托管的不安全代码。

编辑:显然你可以使用乔纳森蔡斯说的属性来建立工会。

如果你能接受不安全的代码,这很简单。

[StructLayout(LayoutKind.Explicit)]
unsafe public struct lng_cnvt
{
[FieldOffset(0)]
public fixed byte cmd[4];
[FieldOffset(0)]
public fixed long data[2];
[FieldOffset(0)]
public long data64;
}

CLR 会将lng_cnvt.cmdlng_cnvt.data视为指针,并且可以使用索引器在unsafe上下文中访问其元素。但是,如果不能接受不安全的代码,则必须通过字段声明建立固定大小的缓冲区,然后编写索引器以提供对正确字段的访问。

[StructLayout(LayoutKind.Explicit)]
public class lng_cnvt
{
private static Dictionary<string, FieldInfo[]> arrayMembers;
static lng_cnvt()
{
arrayMembers = new Dictionary<string, FieldInfo[]>();
arrayMembers.Add("cmd", typeof(lng_cnvt).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).
Where(x => x.Name.StartsWith("cmd")).OrderBy(y => y.Name).ToArray());
arrayMembers.Add("data", typeof(lng_cnvt).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).
Where(x => x.Name.StartsWith("data")).OrderBy(y => y.Name).ToArray());
}
[FieldOffset(0)]
private short cmd0;
[FieldOffset(2)]
private short cmd1;
[FieldOffset(4)]
private short cmd2;
[FieldOffset(6)]
private short cmd3;
[FieldOffset(0)]
private long data0;
[FieldOffset(8)]
private long data1;
[FieldOffset(0)]
public long data64;
public dynamic this[int index, string name = "cmd"]
{
get
{
return arrayMembers[name][index].GetValue(this);
}
set
{
arrayMembers[name][index].SetValue(this, value);
}
}
}