这些 C++ 的 C# 等价物是什么?结构体

发布于 2024-08-22 11:57:36 字数 645 浏览 8 评论 0原文

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#,但在迁移这些结构时遇到问题。我尝试了一些方法,但最终总是遇到编组问题。

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;

What are the C# equivalent of these C++ structs?

I am migrating some code from C++ to C# and having problems to migrate these structures. I had tried a few things but I always ended up having marshalling problems.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

用心笑 2024-08-29 11:57:36

我假设“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# 代码)。

I'm assuming the 'char' is being used as an 8 bit number, if so, then here are you're mappings:

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)

With this info it should be relatively easy to translate those strucutres (just make sure you keep them as a struct and give it the attribute "[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]", which will make sure that the marshaller keeps all the data in the same order.

Also, I recommend looking through both the classes and attributes in System.Runtime.InteropServices as they do provide quite a few methods for automating marshaling of data to c/c++ code (and it doesn't require "unsafe" c# code either).

自此以后,行同陌路 2024-08-29 11:57:36

其他一些帖子已经提供了很好的信息,我想我会分享一个快速提示。我最近不得不经历这样的问题。这可能是显而易见的,但如果您拥有界面两侧的代码,我发现注释掉除一个字段之外的所有字段并确保其有效,然后将它们慢慢地逐一添加回来是一种更安全的方法来实现这一目标。

Some of the other posts already have great information, I thought I would share a quick tip. I had to go through this kind of issue recently. It may be obvious but if you own the code to both sides of the interface I found that commenting out all but the one fields and making sure that works and then adding them back slowly one by one was a much safer way to get this working.

被翻牌 2024-08-29 11:57:36

请参阅这篇 MSDN 文章,了解如何使用 PInvoke 封送结构。

关键是使用 StructLayout 属性来确保 PInvoke 正确处理该结构,并使用 MarshalAs 属性来处理不完全对齐的类型。

See this MSDN article on marshaling structs with PInvoke.

The key is using the StructLayout attribute to ensure that the struct is treated properly by PInvoke, and the MarshalAs attribute for types that don't line up exactly.

罪#恶を代价 2024-08-29 11:57:36

早在 .Net 2.0 时代,我也有一个网络套接字并将字节流转换为有意义的结构。此时,唯一的解决方案是使用 BitConverter< /a> 和 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;
        }
    }
}

Back in .Net 2.0 days i also had a network socket and to convert the byte stream into a meaningful structure. At this time there was the only solution to do it by hand with BitConverter and Buffer class.

Unfortunately i couldn't find the example on the web again. So i stripped down my old class (gosh, this looks so old and ugly...). Maybe due to strip down, there are some small typo errors within it, but it should give you a good idea on how to accomplish the problem.

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;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文