Ich habe es mit einer Reihe nativer Funktionen zu tun, die Daten über dynamisch zugewiesene Arrays zurückgeben. Die Funktionen nehmen einen Referenzzeiger als Eingabe und zeigen ihn dann auf das resultierende Array.C#: Unmanaged Array in eine verwaltete Liste konvertieren
Zum Beispiel:
typedef struct result
{
//..Some Members..//
}
int extern WINAPI getInfo(result**);
Nach dem Aufruf 'Ergebnis' zeigt auf einen null-terminierte Array von Ergebnis *.
Ich möchte eine verwaltete Liste aus diesem nicht verwalteten Array erstellen. Ich kann folgendes tun:
struct Result
{
//..The Same Members..//
}
public static unsafe List<Result> getManagedResultList(Result** unmanagedArray)
{
List<Result> resultList = new List<Result>();
while (*unmanagedArray != null)
{
resultList.Add(**unmanagedArray);
++unmanaged;
}
return result;
}
Dies funktioniert, wird es langweilig und hässlich sein für jede Art von Struktur neu zu implementieren, die ich zu tun haben würde mit (~ 35). Ich möchte eine Lösung, die generisch über den Typ der Struktur im Array ist. Zu diesem Zweck habe ich versucht:
public static unsafe List<T> unmanagedArrToList<T>(T** unmanagedArray)
{
List<T> result = new List<T>();
while (*unmanagedArray != null)
{
result.Add((**unmanagedArray));
++unmanagedArray;
}
return result;
}
Aber das wird nicht kompilieren, weil Sie nicht „die Adresse nehmen, erhalten die Größe, oder zu erklären, einen Zeiger auf einen verwalteten Typen (‚T‘)“.
Ich habe auch versucht, dies ohne unsafe Code zu tun, aber ich lief auf das Problem, dass Marshal.Copy() die Größe des nicht verwalteten Array kennen muss. Ich konnte dies nur mit unsicherem Code feststellen, daher schien es keinen Vorteil zu geben, in diesem Fall Marshal.Copy() zu verwenden.
Was fehlt mir? Könnte jemand einen generischen Ansatz für dieses Problem vorschlagen?
Marshal.Copy muss wissen, wie viele Elemente sich im Quell-Array befinden, aber das weiß ich zur Kompilierzeit nicht, da das Array dynamisch vom systemeigenen Code zugewiesen wird. Ich kenne keine Möglichkeit, die Anzahl der Elemente im nicht verwalteten Array zu ermitteln, ohne unsicheren Code zu verwenden. – Odrade
Objekt ist auch ein verwalteter Typ. Wie oben erwähnt, können Sie keine unsicheren Operationen für einen verwalteten Typ ausführen. – Odrade
Im schlimmsten Fall können Sie einen IntPtr für den Parameter Ihrer Funktion verwenden und dann Marshal.Copy() einmal für jedes Element im Array aufrufen, bis Sie das Ende erreicht haben. Sie sollten in der Lage sein, dies zu verkürzen, indem Sie eine Kopie des übergebenen IntPtr mit Marshal erstellen.SizeOf(), um die richtige Größe zu bestimmen, als diese Größe in einer Schleife hinzuzufügen, bis Sie den Nulleintrag gefunden haben. –