StructLayout-Size

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von seh.

    StructLayout-Size

    Hallo zusammen,

    ich will Klassen die in unverwaltetem Speicher liegen in C# marshallen.

    Dazu baue ich die Klasse in C# nach und lese die Größe der Klasse in Bytes an der richtigen Stelle im Speicher des Zielprozesses. Danach wird das Byte Array mit Marshal.PtrToStructure() in die nachgebaute Klasse gemarshallt.

    Jetzt verstehe ich bei dem StructLayout Attribut noch den Size Parameter nicht so ganz.

    Mit LayoutKind kann ich ja definieren, ob Sequentiell oder Explizit. Wenn Sequentiell, werden die Member in der Reihenfolge wie sie in der Klasse vorkommen gemarshallt. Wenn Explizit, muss jeder Member ein FieldOffset aufweisen.
    Wie ist das allerdings wenn ich eine Klasse habe, die eine Superklasse hat. D.h. z.B. haben wir die Basisklasse Fahrzeug die jetzt sag ich mal 4 Byte groß ist weil sie genau einen Member z.B. AnzahlRaeder hat (Int32).

    Wenn ich dann eine Klasse Auto habe, die noch den zusätzlichen Member AnzahlTueren hat (Int32) dann ist die Klasse Auto eigentlich 8 Byte groß.

    Jetzt baue ich also beide Klassen nach. Bei der Klasse Fahrzeug gebe ich LayoutKind Explizit und Size = 4 an und bei Auto LayoutKind Explizit und Size 8 an. Der Size Parameter besagt, das die absolute Größe der Klasse angegeben werden soll. Ist das so also richtig ? Oder muss ich bei Fahrzeug dann auch 4 Bytes angeben weil die Superklasse nicht dazu gezählt wird?

    Außerdem meine Frage: Wenn die LayoutKinds explizit sind, wie läuft es dann mit Vererbung? AnzahlRaeder in der Fahrzeug Klasse hat dann FieldOffset 0 und AnzahlTueren in der Auto Klasse hat dann FieldOffset 4 oder auch FieldOffset 0? Sind die relativ oder wie verhalten die sich?

    Danke im Voraus
    ich versteh von der Materie nur sehr wenig.
    Aber ich hab den Eindruck, du wirfst Struct und Class fröhlich durcheinander - bist du dir sicher, dass du mit .PtrToStructure iwas in eine "nachgebaute" Klasse marshallen kannst?
    Wenn nicht, ist das mit der Vererbung auch geschwätzt - Structures kann man nicht beerben.
    Klasse == Struct wenn wir von C++ sprechen. Da ist es nicht so komisch wie in .Net. Schreibst du die zu marshallenden Klassen selbst? Wenn ja würde ich empfehlen die API einfach in C bereit zu stellen. Dann kannst du einfach über P/Invoke arbeiten. Ansonsten zeig doch einfach mal die betreffenden Klassen
    Hi
    in diesem Fall macht es keinen Unterschied, ob Klasse oder Struktur, da beide Instanzen im Heap abgelegt werden. Strukturen liegen in Object boxed vor. Bei meinen damaligen Tests hat die Funktion auch für Klassen korrekt funktioniert - was an sich nicht weiter verwunderlich ist, solange das Layout explizit oder sequentiell ist.
    Wenn du C# verwendest, kannst du eigentlich auch auf unsafe zurückgreifen. Du musst dann allerdings selbst darauf achten, dass die Daten korrekt aufeinander abgebildet werden.

    Bzgl. Vererbung habe ich das noch nicht überprüft, aber du kannst die Daten mal auslesen, z.B. über GCHandle. Wo in .Net die VTable abgelegt wird, kann ich auch nicht beantworten. Habe ich selbst noch nicht nachgeschaut. Wo es auch stehen sollte, wäre die ECMA-335 oder die Spezifikation der virtuellen Maschine oder die Spezifikation des Aufbaus der Assemblies und deren Ausführung.
    An sich würde ich aber eher auf Vererbung verzichten und manuell einen Wrapper schreiben oder mehrere Structures implementieren (ggf. über T4-Templates).

    Viele Grüße
    ~blaze~

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    Gonger96 schrieb:

    Klasse == Struct wenn wir von C++ sprechen. Da ist es nicht so komisch wie in .Net. Schreibst du die zu marshallenden Klassen selbst? Wenn ja würde ich empfehlen die API einfach in C bereit zu stellen. Dann kannst du einfach über P/Invoke arbeiten. Ansonsten zeig doch einfach mal die betreffenden Klassen

    Die kann ich leider nicht beinflussen.

    @~blaze~ Ich werde mir jetzt die Zeit nehmen und in Ruhe überprüfen wie sich das ganze mit Vererbung verhält. Wenn mir dabei dann aufällt, das der vTable Pointer anders gelegt wird, lasse ich es mit den Klassen bilden sein und lese die Werte aus den Klassen die ich brauche mit ReadProcessMemory einzeln aus.
    Wenn ich mehr weiß, berichte ich hier.