13. marts 2009 - 22:04Der er
10 kommentarer og 1 løsning
C++ struct til C#
Hej,
Jeg har følgende struct fra C++:
typedef struct { char Name[ TB_UNIT_NAME_MAX ]; int SwitchAddress; int PlugNo; // 0..5 TTB_UNIT_TYPE UnitType; bool Online; bool OpenClosePending; // Command sent to unit, but no confirmed yet. bool Open;
union { struct { float EnergyKWh; // Since last reset float LastResetEnergyKWh; // Total energy until last reset TTB_DATE_TIME LastResetDateTime; // Timestamp of last reset } EnergyB; // Switch B2 & B6
struct { float EnergyKWh; // KWh (updated for each 0,1 KWh) int WaterUnits; int SequenceNo; // Incremented for each new payment (0..255) TTB_PAY_TYPE PayType; unsigned long CardSerialNumber; // 32bit card serial number int CardID; int UnitID; float UserValue; } EnergyTCM; // TCM+
char Buffer[ 40 ]; // Reserve space for up to 40 bytes } u; } TTB_UNIT_DATA;
Som jeg prøver at konvertere til C#. Jeg bøvler lidt med hvordan jeg skal få placeret Bufferen der er inde i union'en.
Jeg har følgende som dog giver en fejl:
[StructLayout(LayoutKind.Sequential, Pack = 2)] public struct TBUnitData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] public sbyte[] UnitName;
public int SwitchAddress; public int PlugNo; // 0..5 public TBUnitType UnitType; public bool Online; public bool OpenClosePending; // Command sent to unit, but no confirmed yet. public bool Open;
public Energy Energy; }
[StructLayout(LayoutKind.Explicit, Pack = 2)] public struct Energy { [FieldOffset(0)] public EnergyB EnergyB; [FieldOffset(0)] public EnergyTCM EnergyTCM; [FieldOffset(0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] public sbyte[] Buffer; }
[StructLayout(LayoutKind.Sequential, Pack = 2)] public struct EnergyB { public float EnergyKWh; // Since last reset public float LastResetEnergyKWh; // Total energy until last reset public TBDateTime LastResetDateTime; // Timestamp of last reset } // Switch B2 & B6
[StructLayout(LayoutKind.Sequential, Pack = 2)] public struct EnergyTCM { public float EnergyKWh; // KWh (updated for each 0,1 KWh) public int WaterUnits; public int SequenceNo; // Incremented for each new payment (0..255) public TBPayType PayType; public uint CardSerialNumber; // 32bit card serial number public int CardID; public int UnitID; public float UserValue; }
Fejlen ligger i, at jeg har placeret Buffer'en inde i min Energy struct, men jeg kan ikke gennemskue hvor den ellers skal placeres.
Jeg er derudover også lidt i tvivl om hvorvidt min Pack værdi er korrekt. C++ koden er kompileret med Double-word aligment, men jeg ved ikke om Pack=2 er det korrekte?
Jeg antager at du skal kalde noget C++ med en sådan struct som enten input eller output.
Har du overvejet alterantiver måder: * send data som byte array og brug BinaryReader/BinaryWriter til at processe i C# * lave et lille stykke C++ som konverterer mellem en .NET struct og en native struct ?
namespace E { public class Test { public static void Demo(FooBar fb) { Console.WriteLine(fb.iv); Console.WriteLine(fb.xv); Console.WriteLine(fb.sv); } public static void Main(string[] args) { Wrapper.Passthrough(Demo); } } }
Jeg har fået løst mit problem. Grunden til at den buffer er der, er for at reservere plads op til de 40 bytes. Jeg undlader den bare i min struct - fortæller via StructLayout at den fylder 40 bytes - og så kører det fint. (efter jeg har ændret til Pack = 4)
Arne, smid et svar. Du hjalp med alignment.
Jeg er ikke skarp i C++, så det vil være for stor en fejlkilde, hvis jeg skulle til at skrive en wrapper.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.