typedef union _Value {
signed char c;
unsigned char b;
signed short s;
unsigned short w;
signed long l;
unsigned long u;
float f;
double *d;
char *p;
} Value;
typedef struct _Field {
WORD nFieldId;
BYTE bValueType;
Value Value;
} Field;
typedef struct _Packet {
WORD nMessageType;
WORD nSecurityType;
BYTE bExchangeId;
BYTE bMarketCenter;
int iFieldCount;
char cSymbol[20];
Field FieldArr[1];
} Packet;
这些C ++结构的C#等价物是什么?
我正在将一些代码从C ++迁移到C#,并且在迁移这些结构时遇到问题。我曾尝试过一些东西,但我总是遇到编组问题。
答案 0 :(得分:13)
我假设'char'被用作8位数字,如果是这样,那么这里是你的映射:
signed char c; -> SByte c;
unsigned char b; -> Byte b;
signed short s; -> Int16 s;
unsigned short w; -> UInt16 w;
signed long l; -> Int32 l;
unsigned long u; -> UInt32 u;
float f; -> Single f; (though 'float' still works)
double *d; -> Double d; (was this meant to be a pointer???)
char *p; -> String s; (assuming its a string here, in the marshaling you can tell it whether it is ASCII or wide char format)
使用此信息,翻译这些结构应该相对容易(只需确保将它们保留为结构并赋予其属性“[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)) ]“,这将确保编组器以相同的顺序保存所有数据。
另外,我建议查看System.Runtime.InteropServices中的类和属性,因为它们提供了很多方法来自动将数据封送到c / c ++代码(并且它不需要“不安全”的c#代码任一)。
答案 1 :(得分:0)
使用PInvoke查看关于编组结构的this MSDN article。
关键是使用StructLayout
属性来确保PInvoke正确处理结构,并且MarshalAs
属性用于不完全对齐的类型。
答案 2 :(得分:0)
其他一些帖子已经有很多信息,我想我会分享一个快速提示。我最近不得不经历这样的问题。这可能是显而易见的但是如果你拥有接口双方的代码我发现除了一个字段之外的所有内容并且确保工作然后逐个缓慢地添加它们是一种更加安全的方式来实现这一点。
答案 3 :(得分:-1)
回到.Net 2.0天,我还有一个网络套接字,并将字节流转换为有意义的结构。目前,唯一的解决方案是BitConverter和Buffer类手动完成。
不幸的是我再也找不到网上的例子了。所以我剥夺了我的旧班级(天哪,这看起来很古老,丑陋......)。也许由于条带化,其中有一些小错字错误,但它应该让你对如何解决问题有个好主意。
using System;
using System.Collections.Generic;
using System.Text;
namespace VehicleSpeedTracer
{
public class Datagram
{
//Offsets im ByteArray
private const int SizeOffset = 0;
private const int TimeOffset = SizeOffset + sizeof(uint);
private const int SpeedOffset = TimeOffset + sizeof(double);
private const int UnitOffset = SpeedOffset + sizeof(char);
private const int UnitMaxSize = (int)MaxSize - UnitOffset;
//Daten Current
public const uint MaxSize = 128;
public TimeSpan CurrentTime;
public double CurrentSpeed;
public string Unit;
public uint Size
{
get { return MaxSize - (uint)UnitMaxSize + (uint)Unit.Length; }
}
public Datagram()
{
}
public Datagram(Datagram Data)
{
CurrentTime = Data.CurrentTime;
CurrentSpeed = Data.CurrentSpeed;
Unit = Data.Unit;
}
public Datagram(byte[] RawData)
{
CurrentTime = TimeSpan.FromSeconds(GetDouble(RawData, TimeOffset));
CurrentSpeed = GetDouble(RawData, SpeedOffset);
Unit = GetString(RawData, UnitOffset, (int)(GetUInt(RawData, SizeOffset) - UnitOffset));
}
public override string ToString()
{
return this.CurrentTime.Hours.ToString().PadLeft(2, '0') + ":" +
this.CurrentTime.Minutes.ToString().PadLeft(2, '0') + ":" +
this.CurrentTime.Seconds.ToString().PadLeft(2, '0') + "." +
this.CurrentTime.Milliseconds.ToString().PadLeft(3, '0') + " " +
this.Unit;
}
public static implicit operator byte[](Datagram Data)
{
byte[] RawData;
RawData = new byte[Data.Size];
SetUInt(RawData, SizeOffset, Data.Size);
SetDouble(RawData, TimeOffset, Data.CurrentTime.TotalDays);
SetDouble(RawData, SpeedOffset, Data.CurrentSpeed);
SetString(RawData, UnitOffset, Data.Unit);
return RawData;
}
#region Utility Functions
// utility: get a uint from the byte array
private static uint GetUInt(byte[] aData, int Offset)
{
return BitConverter.ToUInt32(aData, Offset);
}
// utility: set a uint into the byte array
private static void SetUInt(byte[] aData, int Offset, uint Value)
{
byte[] buint = BitConverter.GetBytes(Value);
Buffer.BlockCopy(buint, 0, aData, Offset, buint.Length);
}
// utility: get a ushort from the byte array
private static ushort GetUShort(byte[] aData, int Offset)
{
return BitConverter.ToUInt16(aData, Offset);
}
// utility: set a ushort into the byte array
private static void SetUShort(byte[] aData, int Offset, int Value)
{
byte[] bushort = BitConverter.GetBytes((short)Value);
Buffer.BlockCopy(bushort, 0, aData, Offset, bushort.Length);
}
// utility: get a double from the byte array
private static double GetDouble(byte[] aData, int Offset)
{
return BitConverter.ToDouble(aData, Offset);
}
// utility: set a double into the byte array
private static void SetDouble(byte[] aData, int Offset, double Value)
{
byte[] bushort = BitConverter.GetBytes(Value);
Buffer.BlockCopy(bushort, 0, aData, Offset, bushort.Length);
}
// utility: get a unicode string from the byte array
private static string GetString(byte[] aData, int Offset, int Length)
{
String sReturn = Encoding.ASCII.GetString(aData, Offset, Length);
return sReturn;
}
// utility: set a unicode string in the byte array
private static void SetString(byte[] aData, int Offset, string Value)
{
byte[] arr = Encoding.ASCII.GetBytes(Value);
Buffer.BlockCopy(arr, 0, aData, Offset, arr.Length);
}
#endregion
}
public delegate void DatagramEventHandler(object sender, DatagramEventArgs e);
public class DatagramEventArgs : EventArgs
{
public Datagram Data;
public DatagramEventArgs(Datagram Data)
{
this.Data = Data;
}
}
}