2010-12-08 4 views
3

Meine Frage hat damit zu tun, eine in C geschriebene Funktion von C# aufzurufen. Ich habe in einer Headerdatei gesucht, die mit der C-Bibliothek geliefert wurde, um die Funktionen zu verstehen, die in der C-DLL vorhanden sind. Hier ist, was ich sehe:Wie wird ein C-Array zu C# zugeordnet?

C-Code (für eine Funktion "LocGetLocations" genannt):

typedef enum { 
    eLocNoError, 
    eLocInvalidCriteria, 
    eLocNoMatch, 
    eLocNoMoreLocations, 
    eLocConnectionError, 
    eLocContextError, 
    eLocMemoryError 
} tLocGetStatus; 

typedef void *tLocFindCtx; 

typedef void *tLocation;  

PREFIX unsigned int POSTFIX LocGetLocations 
(
    tLocFindCtx pCtx, 
    tLocation *pLoc, 
    unsigned int pNumLocations, 
    tLocGetStatus *pStatus 
); 

In C#, ich habe dies:

[DllImport(@"VertexNative\Location.dll")] 
public static extern uint LocGetLocations(IntPtr findContext, out byte[] locations, uint numberLocations, out int status); 

Das Problem ist, dass ich nicht weiß ziemlich genau wie man mit dem pLoc Parameter in C# umgeht. Ich bringe es als Byte-Array mit, obwohl ich mir nicht sicher bin, ob das korrekt ist. Die Dokumentation der C-Bibliothek besagt, dass dieser Parameter ein Zeiger auf ein Array von Handles ist.

Wie kann ich ein Array zurück auf der C# -Seite bekommen und auf seine Daten zugreifen?

Das Beispiel, das ich in C gegeben wurde, sieht wie folgt aus:

tLocation lLocation[20]; 

// other stuff 

LocGetLocations(lCtx, lLocation, 20, &lStatus) 

Jede Hilfe wäre sehr willkommen!

+2

Wenn es sich um ein Array von Handles handelt, sollten Sie es zu einem Array von 'IntPtr' machen. –

+0

Siehe http://pinvoke.net/index.aspx für viele Beispiele. –

Antwort

1

Am Ende dieser Signatur funktioniert:

[DllImport(@"VertexNative\Location.dll")] 
public static extern uint LocGetLocations(IntPtr findContext, [Out] IntPtr[] locations, uint numberLocations, out int status); 

Und ich es so nennen kann (einige Refactoring erforderlich):

IntPtr[] locations = new IntPtr[20]; 
int status; 
// findContext is gotten from another method invocation 
uint result = GeoCodesNative.LocGetLocations(findContext, locations, 20, out status); 

Danke für die Hilfe!

+0

Hinweis, ich denke, es war meine Verwendung des "out" -Schlüsselwortes, das mich stolperte. Das Entfernen hat mich weiter gebracht. Dies ist wahrscheinlich sinnvoll, da Arrays zu Beginn Referenztypen sind und nicht geoutet werden müssen, um dem neuen Wert aus der Methode eine lokale Variable zuzuweisen. –

+0

@Nick: Was Sie wollen, ist das Hinzufügen der [OutAttribute] (oder nur [Out]) zu IntPtr [] Standorten. Dies weist den Marshaller an, nur auf dem Weg nach draußen zu kopieren, nicht sowohl nach innen als auch nach außen. Dies erspart das Speichern einer unnötigen Blockkopie. – Tergiver

+0

Das Hinzufügen zu IntPtr [] - Speicherorten führt jedoch zu einem Laufzeitfehler. –

2

Im Allgemeinen zählt nur die Größe der Parameter. Wie ich mich erinnere, sind Enums ganze Zahlen in C, also kann man das einfach benutzen. Oder besser, erstellen Sie die gleiche Enum in C#, ich denke, es würde funktionieren. Eine Sache, an die man sich erinnern sollte, ist, dass man beim Umgang mit komplexen Strukturen Attribute verwenden muss, um das Framework über die gewünschte Ausrichtung von Mitgliedern zu informieren.

Verwandte Themen