Bonjour,
j'ai une DLL développée sous Embarcadero Delphi que je voudrais interroger en C#
1) la DLL expose une unique fonction GetInterface(version, Intf) qui retourne une Interface...cette partie fonctionne
2) l'Interface déclare différentes méthodes que je peux invoquer, les paramètre en entrée sembles bon, mais en sortie ça ne fonctionne pas
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 [DllImport("MaDLL.dll", CallingConvention = CallingConvention.StdCall)] public static extern int GetInterface(int RequestedVersion, out IMonInterface Inf);
voici la déclaration Delphi
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 public interface IMonInterface { int getVersion; // me retourne toujours 0 IntPtr GetMsg(); // me retourne toujours 0 void SetLogger(ILogger log); // ça fonctionne } public interface ILogger { void OnLog([MarshalAs(UnmanagedType.LPWStr)] string msg); } ... class Log: ILogger { public void OnLog(string Msg) { Console.WriteLine("[LOG] " + Msg); // ça fonctionne ! } }
Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 type ILogger = interface procedure OnLog(Msg: PChar); stdcall; end; IMonInterface = interface function GetVersion: Integer; stdcall; function GetMsg: PChar; stdcall; procedure SetLogger(Logger: ILogger); stdcall; end; function GetInterface(Version: Integer; out Intf: IMonInterface): Integer; stdcall; external 'MaDLL.dll';
je vous donne la version C qui fonctionne très bien
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 typedef struct { int (__stdcall *QueryInterface)(void *this, void *riid, void*); int (__stdcall *AddRef)(void *this); int (__stdcall *Release)(void *this); void (__stdcall *OnLog)(void *this, wchar_t* Msg); } **ILogger; typedef struct { int (__stdcall *QueryInterface)(void *this, void *riid, void*); int (__stdcall *AddRef)(void *this); int (__stdcall *Release)(void *this); int (__stdcall *GetVersion)(void *this); wchar_t* (__stdcall *GetMsg)(void *this); void (__stdcall *SetLogger)(void *this, ILogger Logger); } **IMonInterfacce; __stdcall int GetInterface(int RequestedVersion, IMonInterface *Intf);
j'ai donc du stdcall partout, et la fonction GetMsg me retourne une chaine ASCIIZ unicode statique (qu'il ne faut pas libérer)
je soupçonne un problème de convention d'appel sur l'interface mais je n'ai pas trouvé d'information sur le sujet, quelle est la convention par défaut, comment la changer ?
et question bonus - pour quand ça fonctionnera - peut-on éviter le InPtr avec un Marshal.PtrToStringUni(ptr) ? d'ailleurs le OnLog est-il correct ? là encore la chaîne ne DOIT pas être libérée.
Merci !
Partager