utiliser une DLL fournie dans un projet Visual C++

utiliser une DLL fournie dans un projet Visual C++ - C - Programmation

Marsh Posté le 31-07-2007 à 08:47:53    

Voila ce qui arrive quand on demande a un unixien javateux de faire du C sous windows [:ruisseau de larmes]
 
Bon, j'ai une dll, le .lib qui est censé aller avec, et des fichiers entetes. Je tente un appel quelconque de méthode, pour voir si je suis sur les bons rails :
 

Code :
  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include "api/api_lec.h"
  4. int main(int argc, char **argv)
  5. {
  6. unsigned short pusMode = 0;
  7.     unsigned short pusCodeErreur = 0;
  8.     unsigned short result = 5;
  9.     unsigned char* pcChemin = NULL;
  10. printf("avant\n" );
  11.     //le fameux appel a ma dll
  12.     result = Hn_Init(pcChemin, &pusMode, &pusCodeErreur);
  13. printf("ok: %s\n", result);
  14.     return 0;
  15. }


 
Pour que ca compile, j'ai précisé ces parametres dans mon projet :
* dans "Editeur de liens/General", j'ai "Répertoires de bibliothèques supplémentaires" vers "D:\mon projet\lib" (qui contient le .lib associé a la dll)
* dans "Editeur de liens/Entrées", j'ai "Dépendences supplémentaires" qui contient "api_lec.lib".
 
Je compile, ca roule, pas de warning, ca link, et ca me génère un beau test.exe.
Je l'execute, ca plante.
Je le débugue, il me dit que Hn_Init à l'adresse 0x0000000, autant dire que c'est pas fameux.
En début de débuggage, visual a la bonté de me dire quelles sont les dll chargées, et évidemment, la mienne n'y est pas.
 
Si j'execute "dependency walker" sur mon exe, la dépendence vers ma dll n'est effectivement pas marquée.
 
Mais alors, comment lui dire de dépendre de cette dll, si ajouter le .lib en dépendence ne suffit pas ?
Merci !

Reply

Marsh Posté le 31-07-2007 à 08:47:53   

Reply

Marsh Posté le 31-07-2007 à 09:03:12    

Pour avoir plus d'infos sur l'étape de linkage:
tu as regardé  "Linker > General > Show Progress" ?

Reply

Marsh Posté le 31-07-2007 à 09:07:44    

Je ne connaissais pas, mais je viens d'essayer en le passant en verbeux :
 


Édition des liens en cours...
Début de la passe 2
     test.obj
Fin de la passe 2
Incorporation du manifeste en cours...


Et c'est tout. Aucun message relatif au .lib, donc (pourtant, si je le vire, ca ne linke plus, normal).

Reply

Marsh Posté le 31-07-2007 à 09:11:07    

Ah, tiens, en regenerant j'ai plus d'infos, je ne connaissais pas la génération incrémentielle :
 

Édition des liens en cours...
Début de la passe 1
/DEFAULTLIB:uuid.lib traité
/DEFAULTLIB:MSVCRTD traité
/DEFAULTLIB:OLDNAMES traité
Recherche en cours des bibliothèques
    Recherche en cours D:\projets eclipse\vitale-java\src\jni\vitale-java\lib\api_lec.lib :
    Recherche en cours C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib :
 [...]
    Recherche en cours C:\Program Files\Microsoft Visual Studio 8\VC\lib\MSVCRTD.lib :
      __imp__printf trouvé
        Référencé dans test.obj
        Chargé MSVCRTD.lib(MSVCR80D.dll)
 [...]
      ___xc_a trouvé
        Référencé dans MSVCRTD.lib(crtexe.obj)
        Chargé MSVCRTD.lib(cinitexe.obj)
/DEFAULTLIB:kernel32.lib traité
 /DISALLOWLIB:libc.lib traité
 /DISALLOWLIB:libcd.lib traité
 /DISALLOWLIB:libcmt.lib traité
 /DISALLOWLIB:libcmtd.lib traité
 /DISALLOWLIB:msvcrt.lib traité
      __initterm_e trouvé
        Référencé dans MSVCRTD.lib(crtexe.obj)
        Chargé MSVCRTD.lib(MSVCR80D.dll)
[...]
      __crt_debugger_hook trouvé
        Référencé dans MSVCRTD.lib(gs_report.obj)
        Chargé MSVCRTD.lib(MSVCR80D.dll)
    Recherche en cours C:\Program Files\Microsoft Visual Studio 8\VC\lib\OLDNAMES.lib :
    Recherche en cours D:\projets eclipse\vitale-java\src\jni\vitale-java\lib\api_lec.lib :
    Recherche en cours C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib :
      __imp__InterlockedExchange@8 trouvé
        Référencé dans MSVCRTD.lib(crtexe.obj)
        Chargé kernel32.lib(KERNEL32.dll)
 [...]
    Recherche en cours C:\Program Files\Microsoft Visual Studio 8\VC\lib\OLDNAMES.lib :
    Recherche en cours D:\projets eclipse\vitale-java\src\jni\vitale-java\lib\api_lec.lib :
Fin de la recherche des bibliothèques
Fin de la passe 1
Génération d'une image non-SAFESEH.
Appel de CVTRES.EXE :
 /machine:x86
 /verbose
 /out:"C:\DOCUME~1\fiackv\LOCALS~1\Temp\lnk8A.tmp"
 /readonly
 ".\Debug\test.exe.embed.manifest.res"
Microsoft (R) Windows Resource To Object Converter Version 8.00.50727.42
Copyright (C) Microsoft Corporation. Tous droits réservés.
ajout d'une ressource. type:MANIFEST, name:1, language:0x0409, flags:0x30, size:2048
Début de la passe 2
     test.exe.embed.manifest.res
     test.obj
     kernel32.lib(KERNEL32.dll)
[...]
     MSVCRTD.lib(MSVCR80D.dll)
Fin de la passe 2


 
Mais dans tout ce paté, aucune référence a ma fonction Hn_Init :??:

Reply

Marsh Posté le 31-07-2007 à 09:13:01    

c'est génant il me semble xD
tu peux montrer à quoi ressemble ton api_lec.h ?
 
quand tu passes ta dll dans depends.exe tu vois bien Hn_Init exporté ?

Reply

Marsh Posté le 31-07-2007 à 09:21:14    

BenO a écrit :

c'est génant il me semble xD
tu peux montrer à quoi ressemble ton api_lec.h ?


Il est assez moche.
 

Code :
  1. #ifndef __LEC_H_VU__
  2. #define __LEC_H_VU__
  3. /* plein de defines */
  4. /* [...] */
  5. #ifdef __cplusplus
  6.     /* Compatibilité avec un programme appelant écrit en C++ */
  7.     #define _COMP_CPP   "C"
  8.     #define _EXTERN     extern
  9. #else
  10.     #define _COMP_CPP
  11.     #define _EXTERN
  12. #endif
  13. /* Déclarations des fonctions de la bibliothèque API de Lecture */
  14. #ifdef _API_LEC
  15. #define _DLL_PTR
  16. #else
  17. #ifdef API_ENTRY
  18.  #undef API_ENTRY
  19. #endif
  20.     #if defined(UNIX) || defined(TARGET_API_MAC_OSX)
  21.  #define API_ENTRY /* API*/
  22.      #define _DLL_PTR
  23.     #else
  24.  #define API_ENTRY API
  25.      #define _DLL_PTR *
  26. #endif
  27. #endif
  28. #define API_LEC_EXPORT API_IMPORT_EXPORT API
  29. /********************************************************************/
  30. /* Types des fonctions HAUT NIVEAU de la bibliothèque API de Lecture */
  31. /********************************************************************/
  32. typedef unsigned short  (API_ENTRY  _DLL_PTR T_Hn_Init)
  33.                                 (   IN  unsigned char  FARPTR  pcChemin,
  34.         OUT unsigned short FARPTR    pusMode,
  35.         OUT unsigned short FARPTR    pusCodeErreur );
  36. /* [...] */
  37. #if !defined(APILEC_EXPORTS)
  38. /*********************************************************************************************/
  39. /* Déclaration des pointeurs sur les fonctions HAUT NIVEAU de la bibliothèque API de Lecture */
  40. /*********************************************************************************************/
  41. _EXTERN _COMP_CPP T_Hn_Init     Hn_Init;
  42. /* [...] */
  43. #undef _DLL_PTR
  44. /*
  45. --------------------------------------------------------------------------------------------------
  46. */
  47. #endif


 
 
 

BenO a écrit :

quand tu passes ta dll dans depends.exe tu vois bien Hn_Init exporté ?


Oui, il est bien exporté, je viens de vérifier.  
 
Par contre, quand j'ouvre la dll, j'ai ce message :
"Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module"
 
mais ca n'a pas l'air genant.

Reply

Marsh Posté le 31-07-2007 à 09:27:46    

(ah, la dll elle même fonctionne, je viens de faire un appel par DllCall en autoit, ca me renvoie bien le code erreur que j'attends)

Reply

Marsh Posté le 31-07-2007 à 09:38:49    

je vois pas comme ça >.< dsl

Reply

Marsh Posté le 31-07-2007 à 09:44:17    

pas grave, merci d'avoir cherché :jap:

Reply

Marsh Posté le 31-07-2007 à 09:58:34    

Tu nous mets la partie du .h qui déclare Hn_Init ?

Reply

Marsh Posté le 31-07-2007 à 09:58:34   

Reply

Marsh Posté le 31-07-2007 à 10:09:25    

elle y est déjà (lignes 38 et 49 du snippet du dessus)

Reply

Marsh Posté le 31-07-2007 à 10:41:41    

Bon, j'ai testé la compile en ligne de commande :
 


cl /I "C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include" test.c lib\api_lec.lib


 
même résultat.

Reply

Marsh Posté le 31-07-2007 à 10:56:58    

Y a souvent un #define à mettre quand tu utilises un DLL. En general, il sert à differencer le moment ou tu compiles to DLL de celui ou tu l'utilises. Soit il y est pas et il faut le mettre, soit il y est et il faut l'enlever

Reply

Marsh Posté le 31-07-2007 à 11:28:48    

lorill a écrit :

elle y est déjà (lignes 38 et 49 du snippet du dessus)


Pardon, j'avais pas capté.  
 
Heu, c'est illisible, ce qui fait que je ne peux pas vérifier ce dont JoelF parle: la bonne présence d'un declspec(dllexport) quand tu compiles la dll, et la présence d'un declspec(dllimport) quand tu inclues le .h depuis ton appelant. Tu peux vérifier ça (en appellant le préprocesseur, ou bien en déroulant les macros à la main)

Reply

Marsh Posté le 31-07-2007 à 11:37:14    

ok, je vais voir ca apres manger.

Reply

Marsh Posté le 31-07-2007 à 12:29:12    

bon, pour faire simple, j'ai viré l'include, et ajouté le prototype de la fonction Hn_Init en début de fichier :
 

Code :
  1. __declspec(dllimport)  unsigned short  Hn_Init(const unsigned char*, unsigned short*, unsigned short*);


 
mais du coup, j'ai une erreur au link :

test.obj : error LNK2001: symbole externe non résolu __imp__Hn_Init


 
d'ou vient le __imp__ ?

Reply

Marsh Posté le 31-07-2007 à 12:42:59    

l'idée c'est d'avoir un truc comme ça dans ton .h
 

Code :
  1. #ifdef MY_DLL_EXPORTS
  2. #define MY_DLL __declspec(dllexport)
  3. #else
  4. #define MY_DLL __declspec(dllimport)
  5. #endif
  6. extern "C" MY_DLL int myFunctionvoid);


 
Ensuite de définir (ou pas) MY_DLL_EXPORTS dans les settings de ton projet (tu as l'air d'être sous visual6).


---------------
Töp of the plöp
Reply

Marsh Posté le 31-07-2007 à 12:54:54    

_darkalt3_ a écrit :

l'idée c'est d'avoir un truc comme ça dans ton .h

 
Code :
  1. #ifdef MY_DLL_EXPORTS
  2. #define MY_DLL __declspec(dllexport)
  3. #else
  4. #define MY_DLL __declspec(dllimport)
  5. #endif
  6. extern "C" MY_DLL int myFunctionvoid);
 

Ensuite de définir (ou pas) MY_DLL_EXPORTS dans les settings de ton projet (tu as l'air d'être sous visual6).


le truc c'est que je ne peux pas recompiler la dll, ni savoir comment elle a été compilée. Mais vu que les symboles sont trouvés par depends, ca doit être bon, non ? (non, e suis sous visual express 2003)

 

donc j'ai mis ce paté :

Code :
  1. #define MY_DLL __declspec(dllimport)
  2. extern "C" MY_DLL unsigned short Hn_Init(const unsigned char*, unsigned short*, unsigned short*);
 

mais il me ressort l'erreur du symbole __imp__XXX introuvable

Message cité 1 fois
Message édité par lorill le 31-07-2007 à 12:56:42
Reply

Marsh Posté le 31-07-2007 à 13:17:02    

lorill a écrit :

mais il me ressort l'erreur du symbole __imp__XXX introuvable


Elle a probablement été mal compilée alors : le .lib ne contient pas de __imp__XXX, alors même que tu en veux un vu que tu importes un truc d'une dll.
Et pour qu'il contienne le __imp__XXX, il faudrait que la dll soit compilée avec le __declspec(dllexport).

 

Bon, tu dois pouvoir te débrouiller avec un .def, ou bien en utilisant le couple LoadLibrary/GetProcAddress dans ton code appellant.


Message édité par Lam's le 31-07-2007 à 13:17:39
Reply

Marsh Posté le 31-07-2007 à 13:32:02    

le LoadLibrary marche, c'est ma solution de secours.
Tu peux m'en dire plus sur le .def ?

Reply

Marsh Posté le 31-07-2007 à 13:39:02    

Chaipas exactement comment faire simple. Essaye donc ça:
  http://support.microsoft.com/kb/131313
 
 

Reply

Marsh Posté le 31-07-2007 à 13:57:11    

ok, merci. J'ai du louper quelque chose quand même :
 
1. J'exporte la liste des symboles avec dumbin, j'en fait un fichier .def
2. Je transforme le .def en .lib avec lib /def:XXX
3. Je link contre la lib générée
 
=> aucune dépendence a la dll dans l'exe généré, et il plante toujours de la même manière :(
Le pire, c'est que je suis sur qu'il manque pas grand chose.

Reply

Marsh Posté le 31-07-2007 à 21:31:23    

lorill a écrit :

ok, merci. J'ai du louper quelque chose quand même :
 
1. J'exporte la liste des symboles avec dumbin, j'en fait un fichier .def
2. Je transforme le .def en .lib avec lib /def:XXX
3. Je link contre la lib générée
 
=> aucune dépendence a la dll dans l'exe généré, et il plante toujours de la même manière :(
Le pire, c'est que je suis sur qu'il manque pas grand chose.


si t'utilises loadlibrary / GetProcAdress, je crois pas que t'aies besoin de .def, juste des prototypes que tu recherches et de la dll.


---------------
Töp of the plöp
Reply

Marsh Posté le 01-08-2007 à 08:36:07    

_darkalt3_ a écrit :


si t'utilises loadlibrary / GetProcAdress, je crois pas que t'aies besoin de .def, juste des prototypes que tu recherches et de la dll.


Le but, c'était justement de pas se faire chier avec les GetProcAddress, mais je n'ai pas le choix finalement.
 
Par contre, j'ai cette erreur :
 


Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.


 
en googlant, j'ai vu que si je passait en release, y'aurait plus ce message, mais ca me semble de la bricole. Une idée ?

Reply

Marsh Posté le 01-08-2007 à 08:52:36    

bon, j'ai trouvé, manquait un _stdcall devant le pointeur de fonction.
y'a plus qu'a.
 
merci a tous :jap:

Reply

Marsh Posté le 26-06-2008 à 17:28:39    

Salut!
Je pense que j'ai le même problème que toi... Peux tu me dire comment tu as fais , ou as tu mis le _stdcall??

Reply

Marsh Posté le 27-06-2008 à 08:02:10    

Code :
  1. //prototypes.h, je déclare mes fonctions externes et leur type
  2. typedef unsigned short (_stdcall *Hn_Init_type)(const unsigned char*, unsigned short*, unsigned short*);
  3. extern Hn_Init_type Hn_Init;


Code :
  1. //a l'endroit ou je charge ma dll
  2. Hn_Init = (Hn_Init_type)GetProcAddress(hDll, "Hn_Init" );
  3. if(Hn_Init == NULL)
  4. {
  5. throw_runtime(env, "Unable to find function: Hn_Init" );
  6. return -1;
  7. }

Reply

Marsh Posté le 27-04-2011 à 14:16:16    

Bonjour
 
Vous pouvez communiquer le code complet de l'appelle de cette DLL ?
 
Comme vous l'aviez fais au tout début du sujet
 
Merci

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed