Kopieren byte-array mit dem Marschall.Kopieren von IntPtr mit C# funktioniert nicht
Ich bin mit einer nicht verwalteten Bibliothek, die erzeugt Graustufen-Bilder (etwa 100x200 Pixel, mehr oder weniger). Ein Bild ist enthalten in einer Struktur, die wie folgt aussieht: C:
typedef struct abs_image {
ABS_DWORD Width;
ABS_DWORD Height;
ABS_DWORD ColorCount;
ABS_DWORD HorizontalDPI;
ABS_DWORD VerticalDPI;
ABS_BYTE ImageData[ABS_VARLEN];
} ABS_IMAGE
typedef unsigned int ABS_DWORD;
typedef unsigned char ABS_BYTE;
Und hier mein C# - wrapper Struktur:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ABS_IMAGE {
public uint Width;
public uint Height;
public uint ColorCount;
public uint HorizontalDPI;
public uint VerticalDPI;
public IntPtr ImageData;
}
Packte das Bild und marshallign die ABS_IMAGE
struct funktioniert Prima. In einer früheren version, ich habe versucht, mit einem byte-array mit fester Länge für die Bilddaten, die manchmal abgestürzt. Dies geschah, glaube ich, weil die Größe des Bildes ist nicht fix.
Jetzt versuche ich das Bild Lesen byte-array zu einem späteren Zeitpunkt, wenn ich kann calulate die real-array der Länge vor. Hier der relevante code:
ABS_Type_Defs.ABS_IMAGE img =
(ABS_Type_Defs.ABS_IMAGE)Marshal.PtrToStructure(
pImage,
typeof(ABS_Type_Defs.ABS_IMAGE));
int length = ((int)img.Height - 1) * ((int)img.Width - 1);
byte[] data = new byte[length];
Marshal.Copy(img.ImageData, data, 0, length);
Nun mein problem: Jedes mal wenn ich Sie ausführen wollen, Marshal.Kopieren Sie Lesen die Bild-bytes, bekomme ich eine AccessViolationException
.
Hat jemand eine Idee?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist, was passiert ist. Ihre Struktur ist, was ist bekannt als eine variable Länge struct. Die pixel-Daten containined inline in der Struktur, beginnend bei offset
ImageData
.Ihre API zurück
pImage
was ist einIntPtr
Punkte, die auf nicht verwaltete Daten TypABS_IMAGE
. Allerdings, wenn Sie einen Blick auf die nativen code, dann werden Sie sehen, dassABS_VARLEN
gleich1
. Dies ist, weil diestruct
definiert werden statisch zur compile-Zeit. In Wirklichkeit sind die pixel-Daten haben die Länge bestimmt sich nach der Höhe, Breite und Farbe, die Anzahl der Felder.Können Sie mit
Marshal.PtrToStructure
zu bekommen am meisten von den Feldern. Aber Sie können nicht an derImageData
Feld Weg. Das wird ein wenig mehr Arbeit.Deklarieren struct wie diesen statt:
Wenn Sie brauchen, um die Bild Daten tun Sie dies:
Wenn Sie noch nicht auf .net 4, dann müssen Sie casting, um die Arithmetik zu kompilieren:
Schließlich, ich glaube, Sie sind der Berechnung
length
falsch. Sicherlich müssen SieHeight*Width
. Auch Sie haben nicht berücksichtigt, die für die Farbtiefe. Zum Beispiel die 32-bit-Farbe werden 4 bytes pro pixel.