2015-09-06 1 views
1

J'ai créé un fichier DLL qui comprend deux fonctions vides ci-dessous.stdcall convention d'appel et en utilisant pinvoke dans C#

extern "C" __declspec(dllexport) void __stdcall myFunc1() { 
    // just empty function 
} 

extern "C" __declspec(dllexport) void __cdecl myFunc2() { 
    // just empty function 
} 

En C#, je pourrais appeler les fonctions utilisant DLLImport attribut comme ci-dessous.

[DllImport("myDLL", CallingConvention=CallingConvention.StdCall)] 
private extern static void myFunc1(); 

[DllImport("myDLL", CallingConvention=CallingConvention.Cdecl)] 
private extern static void myFunc2(); 

donc j'ai essayé à nouveau directement avec LoadLibrary() de kernel32.dll au lieu de DllImport attribut.

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
private delegate void MyFunc1(); 

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
private delegate void MyFunc2(); 

Cependant, une erreur d'exécution se produit lorsque j'appelle MyFunc1() où travaille ma_fonction2().

J'ai donc remplacé __stdcall par __cdecl en C++, recompilé la DLL, puis appelé à nouveau MyFunc1() en C#.

Et .. Cela a fonctionné. Pourquoi ne pas appeler __stdcall convention d'appel avec pinvoke en C#?

+2

'DllImport' * est * P/Invoke. Qu'est-ce que vous essayez de faire sur Terre? : D 'UnmanagedFunctionPointer' gère le rassemblement d'un délégué géré en tant que pointeur de fonction non managé (comme son nom l'indique) - cela n'a rien à voir avec l'appel d'une fonction non managée dans une DLL. D'accord, pas "rien" - évidemment, vous avez un délégué que vous pouvez passer ou recevoir du côté non géré, mais ce n'est pas ce que vous essayez de faire ici. – Luaan

+1

En outre, selon la documentation de 'UnmanagedFunctionPointer',' si vous ne spécifiez pas de nom de champ, UnmanagedFunctionPointerAttribute est ignoré. '- Je ne vous vois pas spécifier de nom. – Luaan

+0

Oui, vous avez raison. J'utilise LoadLibrary(), FreeLibrary() et GetProcAddress() de "kernel32.dll" cette fois. Je n'ai pas posté le reste du code parce que je pensais que c'était juste une chose de base pour les gars experts ici. – Jenix

Répondre

6

Ce qui se passe ici est que lorsque vous passez de __cdecl à __stdcall dans le code C++, le compilateur décore le nom par lequel la fonction est exportée. Au lieu de myFunc1, il est exporté comme [email protected] ou peut-être [email protected]. Tout de même, le nom est décoré. Vous pouvez vérifier qu'il en est ainsi avec dumpbin ou Dependency Viewer. Lorsque vous appelez GetProcAddress, il ne trouve pas de fonction nommée myFunc1 et renvoie NULL. Vous ne vérifiez pas les valeurs de retour, et continuez ainsi. Lorsque vous essayez d'appeler la fonction, une erreur d'exécution est renvoyée.

J'ai dû deviner la plupart de ceci parce que vous n'avez pas montré le code complet. L'autre grande leçon est de vérifier les erreurs lors de l'appel des fonctions Win32.

+0

Merci, je vais vérifier comme vous l'avez dit. Si la raison est la décoration de nom, que puis-je faire? Je pensais que le mot-clé extern "C" permettrait d'éviter les problèmes liés à la dénomination. – Jenix

+2

Besoin d'utiliser un fichier def pour exporter –

+0

Ah d'accord, je vois, merci! – Jenix