Frage

Ich bin (erfolgreich) die Windows-FilterSendMessage Funktion in c # Aufruf der folgende pinvoke Signatur:

[DllImport("fltlib.dll")]
    public static extern IntPtr FilterSendMessage(
        IntPtr hPort,
        IntPtr inBuffer,
        UInt32 inBufferSize,
        IntPtr outBuffer,
        UInt32 outBufferSize,
        out UInt32 bytesReturned);

outBuffer Parameter mit einer beliebigen Anzahl von structs füllt wird (gepackte hintereinander), definiert in C als:

typedef struct _BAH_RECORD {

    int evt
    int len;
    WCHAR name[1];

} BAH_RECORD, *PBAH_RECORD;

Die Namen ist eine variable Länge, nullterminierten Unicode-String zugewiesen. Das len Feld beschreibt die Gesamtgröße der Struktur in Bytes (einschließlich dem Namen string). Ich bin zuversichtlich, es ist nichts falsch mit, wie sich die Strukturen in der nicht verwalteten Seite der Dinge gehandhabt werden.

Mein Problem entsteht, wenn ich versuche, die outBuffer auf eine Instanz des BAH_RECORD struct Marschall, definierte in c # wie:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct BAH_RECORD
{
    public UInt32 evt;
    public UInt32 len;
    public string name;
}

IntPtr outBuffer = Marshal.AllocHGlobal(OUT_BUFFER_SIZE);

hResult = Win32.FilterSendMessage(hPortHandle, inBuffer, IN_BUFFER_SIZE, outBuffer, OUT_BUFFER_SIZE, out bytesReturned);

BAH_RECORD bah = (BAH_RECORD)Marshal.PtrToStructure(outBuffer, typeof(BAH_RECORD));

<snip>

Wenn ich versuche und Druck / Ansicht / Anzeige bah.name, bekomme ich Müll ...

Um zu bestätigen, dass outBuffer tatsächlich gültige Daten enthält, habe ich einige rohe Zeiger hackery in c # wenn es zu dem Schritt, ruft Marshal.ReadInt32 zweimal (die ersten 2 struct Felder abzudecken) und dann Marshal.ReadByte ein paar Mal bevölkern ein byte [], die ich dann als Argument an Encoding.Unicode.GetString verwenden () ... die Zeichenfolge aus fein kommen, so ist es auf jeden Fall drin, ich kann scheinen, um die Einweiser einfach nicht zu bekommen richtig zu handhaben ( wenn es sogar möglich?)

Jede Hilfe willkommen

Steve

War es hilfreich?

Lösung

Das Problem ist, dass der ‚Name‘ String in C # BAH_RECORD Struktur wird als Zeiger auf einen String gemarshallte (WCHAR *), aber auf der C-Seite ist es ein Inline-WCHAR Puffer. Also, wenn Sie Marschall Ihre Struktur der Laufzeit liest die ersten vier Bytes des Puffers als Zeiger und dann versucht, die Zeichenfolge zu lesen, dass es auf.

Leider gibt es keine Möglichkeit für die Laufzeit automatisch variabler Größe Puffer innerhalb structs Marschall, so dass Sie manuell Marshalling verwenden müssen (oder wie Sie „Zeiger hackery“ sagen). Aber wenn Sie den Zeiger vorrücken auf dem Puffer-zu-Punkt müssen Sie nicht einzeln in den Bytes lesen und dann wandeln sie in einen String -. Nur Marshal.PtrToStringUni nennen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top