DLLImport -> comment gérer un manche en C#
dans mon code C# je veux importer une DLL C++. J'utilise le dllimport et il fonctionne très bien avec un certaines fonctions. Mais dans une fonction je obtenir une POIGNÉE dont j'ai besoin plus tard pour appeler une autre fonction.
[DllImport("SiUSBXp.dll")]
public static extern int SI_Open(UInt32 deviceNum,ref IntPtr devHandle ); //this function gets the HANDLE
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write([In]IntPtr devHandle, [In, Out] byte[] inputByte, UInt32 size,ref UInt32 bytesWritten); //this function needs the HANDLE
Dans mon code de ces fonctions sont appelées comme ceci:
IntPtr devHandle = new IntPtr();
UInt32 bytesWritten = new UInt32();
byte[] byteArr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
SI_Open(0, ref devHandle);
SI_Write(devHandle, byteArr, 10, ref bytesWritten);
Si je fais comme ça, je reçois un "Système.AccessViolationException". J'ai cherché ici et sur internet, mais il n'a pas trouver une réponse précise. Comment puis-je utiliser le IntPtr correctement, de sorte qu'il fonctionne?
En Ce Qui Concerne Meilleur
Toby
- Quelle est la fonction C++ prototypes pour SI_Open et SI_Write ressembler?
- Vous êtes initialisation du tableau d'octets à 10 éléments, mais est-ce suffisant pour le SI_Write fonction?
- SI_STATUS WINAPI SI_Open( DWORD dwDevice, la POIGNÉE* cyHandle );
- SI_STATUS WINAPI SI_Write( POIGNÉE cyHandle, LPVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpdwBytesWritten );
- Pour le tableau d'octets => il actuall travaillé avec le "même" tableau dans le Code C++. Aussi j'ai essayé quelque chose -> j'ai initialisé un IntPtr comme ce "IntPtr Test = new IntPtr()" - Lorsque j'appelle la fonction d'Écriture avec cette IntPtr il ne marche pas lever une exception...donc en fait je pense que l'erreur est liée à la IntPtr
Vous devez vous connecter pour publier un commentaire.
Votre SI_Write fonction ressemble tout à fait comme Windows Kernel32 du WriteFile.
Donc, je voudrais faire cela:
MODIFIER: j'ai trouvé cette documentation USBXPRESS® GUIDE DU PROGRAMMEUR sur le web, et il affirme que le SI_Write prototype ressemble en fait beaucoup plus proche de WriteFile que je ne le pensais. La doc stipule ceci:
Cela signifie que le .NET prototype devrait être plutôt ceci:
o est facultatif, de sorte que vous pouvez passer IntPtr.Zéro.
Vous faites un classique programmeur C erreur, vous n'avez pas vérifier la valeur de retour des fonctions. Qui vous dit si oui ou non la fonction a échoué. Un scénario probable est que SI_Open() a renvoyé un code d'erreur. Vous l'ignorez et l'utilisation de la non initialisée poignée de la valeur de toute façon. Un kaboom n'est pas inhabituel.
La prochaine erreur, c'est que vous n'utilisez pas le CallingConvention propriété dans la [DllImport] déclaration. Il est assez probable, Cdecl est la valeur par défaut, à moins que la fonction native est déclarée auprès de __stdcall. Aussi une excellente façon d'invoquer un kaboom. Si vous avez encore des problèmes, alors vous allez avoir à déboguer le code natif.
Btw, vous vous débarrasser de l'ennui, de la syntaxe en utilisant hors au lieu de ref. Dans les deux fonctions.
essayez ceci:
EDIT:
@Hans Passant est droit. C'est la bonne façon de passer un byte[] dans un LPVOID paramètre. ref utilisé pour forcer un objet dans LPVOID, mais n'est pas nécessaire pour un tableau. Ce qui se passe quand vous essayez cela?
Avez-vous essayé la réponse @Simon Mourier a donné? Il a été le premier à fournir cette déclaration et sa réponse mérite d'être accepté.
mauvais:
static extern void DoStuff(**byte[] inputByte**);
bon:
static extern void DoStuff(**[In, MarshalAs(UnmanagedType.LPArray)] byte[] inputByte**);