Gegeben eine DBC-Datei, die von einem Spiel verwendet wird, enthält Datensätze, Informationen über ingame verwendbare Zauber. :) (wie ID, Name, Schaden, etc etc ...)Marshalling.PtrToStructure fällt Ausnahme - Lesen von Bytes zu Strukturen
Um komplexer zu sein, werden die Zeichenfolge Daten in einem Block nach den Datensätzen gespeichert. String-Daten in Datensätze enthalten einen Offset auf den String, (so dass ihr nicht wirklich ein String)
ich eine Struktur für DBC-Datei haben, die wie folgt aussieht:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SpellEntry
{
private const int MAX_EFFECT_INDEX = 3;
public uint ID;
public uint Category;
public uint Dispel;
public uint Mechanic;
public uint Attributes;
public uint AttributesEx;
public uint AttributesEx2;
public uint AttributesEx3;
public uint AttributesEx4;
public uint AttributesEx5;
public uint AttributesEx6;
public uint AttributesEx7;
public uint Stances;
public uint unk_320_2;
public uint StancesNot;
public uint unk_320_3;
public uint Targets;
public uint TargetCreatureType;
public uint RequiresSpellFocus;
public uint FacingCasterFlags;
public uint CasterAuraState;
public uint TargetAuraState;
public uint CasterAuraStateNot;
public uint TargetAuraStateNot;
public uint casterAuraSpell;
public uint targetAuraSpell;
public uint excludeCasterAuraSpell;
public uint excludeTargetAuraSpell;
public uint CastingTimeIndex;
public uint RecoveryTime;
public uint CategoryRecoveryTime;
public uint InterruptFlags;
public uint AuraInterruptFlags;
public uint ChannelInterruptFlags;
public uint procFlags;
public uint procChance;
public uint procCharges;
public uint maxLevel;
public uint baseLevel;
public uint spellLevel;
public uint DurationIndex;
public uint powerType;
public uint manaCost;
public uint manaCostPerlevel;
public uint manaPerSecond;
public uint manaPerSecondPerLevel;
public uint rangeIndex;
public float speed;
public uint modalNextSpell;
public uint StackAmount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] Totem;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I4)]
public int[] Reagent;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.U4)]
public uint[] ReagentCount;
public int EquippedItemClass;
public int EquippedItemSubClassMask;
public int EquippedItemInventoryTypeMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] Effect;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectDieSides;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectBaseDice;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectDicePerLevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectRealPointsPerLevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectBasePoints;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectMechanic;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectImplicitTargetA;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectImplicitTargetB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectRadiusIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectApplyAuraName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectAmplitude;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectMultipleValue;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectChainTarget;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectItemType;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
//public int[] EffectMiscValue;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
//public int[] EffectMiscValueB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectTriggerSpell;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectPointsPerComboPoint;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX)]
public Flag96[] EffectSpellClassMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] SpellVisual;
public uint SpellIconID;
public uint activeIconID;
public uint spellPriority;
[MarshalAs(UnmanagedType.LPStr)]
public string SpellName;
[MarshalAs(UnmanagedType.LPStr)]
public string Rank;
[MarshalAs(UnmanagedType.LPStr)]
public string Description;
[MarshalAs(UnmanagedType.LPStr)]
public string ToolTip;
public uint ManaCostPercentage;
public uint StartRecoveryCategory;
public uint StartRecoveryTime;
public uint MaxTargetLevel;
public uint SpellFamilyName;
public Flag96 SpellFamilyFlags;
public uint MaxAffectedTargets;
public uint DmgClass;
public uint PreventionType;
public uint StanceBarOrder;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] DmgMultiplier;
public uint MinFactionId;
public uint MinReputation;
public uint RequiredAuraVision;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] TotemCategory;
public int AreaGroupId;
public int SchoolMask;
public uint runeCostID;
public uint spellMissileID;
public uint PowerDisplayId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.R4)]
public float[] unk_320_4;
public uint spellDescriptionVariableID;
public uint SpellDifficultyId;
}
[StructLayout(LayoutKind.Sequential)]
public struct Flag96
{
public uint DwA;
public uint DwB;
public uint DwC;
public override string ToString()
{
return string.Format("DwA: {0} - DwB: {1} - DwC: {2}", DwA, DwB, DwC);
}
}
Also, was ich versuche, zu tun ist, Bytes dieser Struktur mit dem folgenden Code Marshalling:
byte[] buff = new byte[Marshal.SizeOf(typeof(Spell.SpellEntry))];
binReader.BaseStream.Seek(DBCFile.HEADER_SIZE + (index * 4 * 234), SeekOrigin.Begin);
var bytes = binReader.ReadBytes(buff.Length);
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var obj = (Spell.SpellEntry)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(Spell.SpellEntry));
handle.Free();
Was gibt mir eine Access auf der Marshal.PtrToStructure Linie. Ich vermute, dass meine Struktur ungültig ist, könnten Sie mich irgendwie korrigieren oder einen Hinweis geben? Was ist interessant, dass, wenn ich in der IDE debuggen, es sieht aus wie es liest die Struktur korrekt, aber gibt diese Ausnahme ... seltsam.
Ich habe versucht auch in struct Lesen eins nach dem anderen, wie
spell[index].ID = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Category = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Dispel = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Mechanic = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
die für mich 100% gut funktioniert, aber sein Aussehen lahm, und es ist wirklich lange im Code. Marshalling sieht mehr pro :) Also, was ist deine Meinung, Marshalsing schneller als das Lesen eines nach dem anderen, wenn ja, wie soll ich es beheben? THanks
Marshalling dient zum Marshalling von Daten zwischen verwaltetem und nicht verwaltetem Code und bietet keine praktische Möglichkeit, Daten in Strukturen zu lesen. Ein [BinaryReader] (http://msdn.microsoft.com/en-us/library/system.io.binaryreader.aspx) ist hier angebracht. – dtb
Ja, das ist die andere Art, wie ich es mache, aber auf einer großen Struktur wie dieser, ist es die richtige, schnellste Methode? –
Ich würde sagen, BinaryReader ist hier die richtige Lösung. Ich habe nicht überprüft, was schneller ist. Nur weil beim Marshalling weniger Codezeilen eingegeben werden müssen, heißt das nicht, dass es schneller sein muss (hinter den Kulissen passiert * viel *; das Marshalling ist nicht nur ein Memcpy). Verwenden Sie einen Profiler. – dtb