2010-12-08 34 views
3

Ma question concerne l'appel d'une fonction écrite en C à partir de C#. J'ai regardé dans un fichier d'en-tête fourni avec la bibliothèque C pour comprendre les fonctions telles qu'elles existent dans la DLL C. Voici ce que je vois:Comment mapper un tableau C en C#?

code C (pour une fonction appelée "LocGetLocations"):

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 
); 

En C#, j'ai ceci:

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

Le problème est que je ne sait très bien comment gérer le paramètre pLoc en C#. Je l'apporte comme un tableau d'octets, même si je ne suis pas sûr que ce soit correct. La documentation de la bibliothèque C indique que ce paramètre est un pointeur vers un tableau de poignées.

Comment puis-je récupérer un tableau du côté C# et accéder à ses données?

L'exemple m'a donné en C, ressemble à ceci:

tLocation lLocation[20]; 

// other stuff 

LocGetLocations(lCtx, lLocation, 20, &lStatus) 

Toute aide serait très apprécié!

+2

Si c'est un tableau de poignées, vous voudrez en faire un tableau de 'IntPtr'. –

+0

Voir http://pinvoke.net/index.aspx pour beaucoup d'exemples. –

Répondre

1

En fin de compte, cela fonctionne la signature:

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

Et je peux l'appeler comme ça (refactoring nécessaire):

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

Merci pour l'aide!

+0

Note, je pense que c'était mon utilisation du mot-clé "out" qui me faisait trébucher. Enlever ça m'a plus loin. Cela est logique, je suppose, puisque les tableaux sont des types de référence pour commencer et n'ont pas besoin d'être sortis pour assigner une variable locale à la nouvelle valeur de la méthode. –

+0

@Nick: Ce que vous voulez, c'est ajouter les [OutAttribute] (ou juste [Out]) aux emplacements IntPtr []. Ceci indique au marshaller de ne copier que sur la sortie, pas à la fois dedans et dehors. Cela évite qu'une copie de bloc inutile ne se produise. – Tergiver

+0

Ajout à des emplacements IntPtr [] me donne cependant une erreur d'exécution. –

2

Généralement, la seule chose qui compte est la taille des paramètres. Si je me souviens que les enums sont des entiers en C, vous pouvez simplement l'utiliser. Ou mieux, recréer la même énumération en C#, je pense que ça marcherait. Une chose à retenir est que lorsqu'il s'agit de structures complexes, il faut utiliser des attributs pour indiquer au framework l'alignement souhaité des membres.