DllImport: impossible de préciser le nom de la fonction
Bonjour,
J'ai créé une solution contenant :
- un projet C#
- un project c++ (unmanaged) type dll, avec export
Dans le projet c++, j'ai une seul méthode, déclaré avec la macro générée par défaut
Code:
1 2
| #define TEST_API __declspec(dllexport)
TEST_API int test(); |
depends.exe et dumpbin me montre tout d'eux ma méthode, qui est bien exportée. (avec le bon nom, j'ai mis la déclaration dans un extern "C")
Dans le projet C#, j'ai la déclaration de cette méthode, et un appel :
Code:
1 2 3
|
[DllImport("test.dll")]
private static extern int test(); |
A l'éxecution j'ai droit à :
Citation:
Impossible de trouver le point d'entrée 'test' dans la DLL 'test.dll'.":"
Si j'ajoute EntryPoint = "test" -> pareil
par contre
si j'ajoute EntryPoint = "#1" // étant l'ordinal de ma méthode -> ça marche
Le pb est que ceci n'est qu'un prototype, et que j'aurai des 10ène de méthodes par la suite, je ne peux pas m'appuyer sur l'ordinal (étant "variable")
Je ne comprends pas pourquoi la méthode n'est pas trouvé par nom...
Si quelqu'un a déjà eu ce pb, une solution me ferai très plaisir :)
Merci !
.µAlexx.
mangling,unmangling name in c++ & mfc c++
Rebonjour MicroAlexx
pour le probleme du mangling et unmangling des noms des symboles c'est l'un des grands problemes de c++ & mfc++.
Microsoft dispose meme d'une Api peu connue et mal documente pour automatiser le "unmangling" c.à.d remplacer les noms "mangles" qui sont un codage reellement par les noms des symboles originaux.
le "mangling" est du à la directive __declspec.
la directive extern "C" utilise en C (pas c++) genere des noms au format ansi normaux.
d'ou l'idee astucieuse pour certains d'ecrire carrement un Wrapper en C++ pure (qu'il ne faut confondre avec le wrapper c++/cli) avec une directice extern "C" pour chaque fonction et c'est lui qu'on appelle.
Car pour appeler ta dll à partir de vb.net(qui ne differe pas de c#) j'ai eu le meme probleme.
voici le code c++ de pinvokemacro avec l'adjonction de petits wrappers c++ pour chaque fonction exporte de la classe assez simple:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
// Le bloc ifdef suivant est la façon standard de créer des macros qui facilitent l'exportation
// à partir d'une DLL. Tous les fichiers contenus dans cette DLL sont compilés avec le symbole PINVOKEMACRO_EXPORTS
// défini sur la ligne de commande. Ce symbole ne doit pas être défini dans les projets
// qui utilisent cette DLL. De cette manière, les autres projets dont les fichiers sources comprennent ce fichier considèrent les fonctions
// PINVOKEMACRO_API comme étant importées à partir d'une DLL, tandis que cette DLL considère les symboles
// définis avec cette macro comme étant exportés.
#ifdef PINVOKEMACRO_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
// Cette classe est exportée de PInvokeMacro.dll
class TEST_API CPInvokeMacro {
public:
CPInvokeMacro(void);
// TODO*: ajoutez ici vos méthodes.
static int funcClass(int foo);
};
int TEST_API CPInvokeMacro::funcClass(int foo)
{
return foo*100;
}
//le wrapper de funcClass
extern "C"
TEST_API int FuncClassExtern(int foo)
{
return CPInvokeMacro::funcClass( foo);
};
extern TEST_API int nPInvokeMacro;
//
TEST_API int fnPInvokeMacro(void);
//
//le wrapper de fnPInvokeMacro
extern "C"
TEST_API int FuncPInvokeMacro(void)
{
return ::fnPInvokeMacro();
}; |
ici le code vb.net pour appeler les fonctions:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
'Un Module partage avec (equivalent de la directive statique en #)
Imports System
Imports System.Runtime.InteropServices
Module PInvokeModule
'Exemple c#
' [DllImport("test.dll")]
'private static extern int test();
'Exemple VB
' Use DllImport to import the PInvokeMacro
<DllImport("PInvokeMacro.dll", CharSet:=CharSet.Auto)> _
Function FuncPInvokeMacro() As Integer
End Function
<DllImport("PInvokeMacro.dll", CharSet:=CharSet.Auto)> _
Function FuncClassExtern(ByVal nbEntier As Integer) As Integer
End Function
End Module
'le code du WinForm
Imports System
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub btnPINVOKE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPINVOKE.Click
Me.txtPINVOKE.Text = FuncPInvokeMacro.ToString
Dim NBENTIER As Integer = 15
Me.TextBox1.Text = FuncClassExtern(NBENTIER).ToString
End Sub
End Class |
Voila un remede à la versatilite du P/Invoke.
bon code.............