IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

appel fonction DLL


Sujet :

Windows

  1. #1
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut appel fonction DLL
    Bonjour,

    j'ai besoin de communiquer avec un lecteur de carte à puce. Pour celà, j'ai besoin de faire appel à winscard.dll. Je travaille en C/C++ sous visual studio.

    J'ai pour l'instant un fichier qui contient le main:
    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
    18
    19
    20
    21
    22
    23
    24
    // ACR38.cpp : définit le point d'entrée pour l'application console.
    //
    
    #include "stdafx.h"
    #include <winscard.h>
    #include "Load_Winscard_DLL.h"
    
    #define IOCTL_SMARTCARD_SET_CARD_TYPE SCARD_CTL_CODE(2060)
    
    int main() {
        long rv;
        long nCardType = 15; // SLE4418 – refer to inf for more info
        BYTE cbOutBuffer[10];
        SCARDCONTEXT hctx;
        SCARDHANDLE hsc;
        DWORD dwActiveProtocol;
        DWORD dwBytesRet;
    
        linkDLL();
        rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM,NULL,NULL,&hctx);
        if (rv != SCARD_S_SUCCESS)
            return rv;
        unlinkDLL();
    }
    un .h et un .cpp qui contiennent ce qu'il faut pour pouvoir appeler la DLL:
    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
    18
    19
    20
    21
    22
    23
    // LoadWinscard.h
    #ifndef _Load_Winscard_DLL_
    #define _Load_Winscard_DLL_
    #include <windows.h>
    #include <winscard.h>
    
    /*void  Out32(short portaddr, short data);        //    Ecriture d'une donnée dans le port*/
    LONG WINAPI SCardEstablishContext (
      DWORD ,
      LPCVOID ,
      LPCVOID ,
      LPSCARDCONTEXT );
      
    /****************************************************************************************
    ***    Liaison des fonctions à la DLL                                                  ***
    ****************************************************************************************/
    int linkDLL(void);
    
    /****************************************************************************************
    ***    Libération                                                                      ***
    ****************************************************************************************/
    void unlinkDLL(void);
    #endif
    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
    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
    43
    44
    45
    46
    // LoadWinscard.cpp
    #include "stdafx.h"
    #include "Load_Winscard_DLL.h"
    
    //**** winscard.dll ****************************************************************
    typedef LONG WINAPI (_stdcall *SCardEstablishContextfuncptr) (
      DWORD ,
      LPCVOID ,
      LPCVOID ,
      LPSCARDCONTEXT);
    
    SCardEstablishContextfuncptr SCardEstablishContextfp;
    LONG WINAPI SCardEstablishContext (
      DWORD dwScope,
      LPCVOID pvReserved1,
      LPCVOID pvReserved2,
      LPSCARDCONTEXT phContext){
        (SCardEstablishContextfp) (
              dwScope,
              pvReserved1,
              pvReserved2,
              phContext);
        }
    
    //*** Linkage des fonctions à la librairie *****************************************
    
    HINSTANCE hLib1;
    
    int linkDLL(void) {
         hLib1 = LoadLibrary(_T("winscard.dll"));
         if (hLib1 == NULL) {
              fprintf(stderr,"LoadLibrary Failed.\n");
              return -1;
         }
    
     SCardEstablishContextfp = (SCardEstablishContextfuncptr)(hLib1, "SCardEstablishContext");
         if (SCardEstablishContextfp == NULL) {
              fprintf(stderr,"GetProcAddress for SCardEstablishContext Failed.\n");
              return -1;
         }
              return 0;
    }
    
    void unlinkDLL(void){
         FreeLibrary(hLib1);
    }
    Je joins également le prototype de la fonction que je veux appeler dans la DLL (d'après msdn)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    LONG WINAPI SCardEstablishContext(
      __in   DWORD dwScope,
      __in   LPCVOID pvReserved1,
      __in   LPCVOID pvReserved2,
      __out  LPSCARDCONTEXT phContext
    );
    J'ai une erreur à la compilation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur    1    error C2059: erreur de syntaxe : '('
    qui pointe sur le typedef dans // LoadWinscard.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef LONG WINAPI (_stdcall *SCardEstablishContextfuncptr) (
      DWORD ,
      LPCVOID ,
      LPCVOID ,
      LPSCARDCONTEXT);
    J'ai déjà fait appel à des DLL avec succès, mais là je ne vois pas quel est le problème. Des idées?
    Merci

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 376
    Points : 41 544
    Points
    41 544
    Par défaut
    Déjà, ça me parait bizarre de voir WINAPI et _stdcall dans la même ligne (ça correspond à mettre deux fois __stdcall).

    Ensuite, ne serait-il pas plus simple de lier "implicitement" à la DLL, vu que ton programme la charge directement par nom et quitte en cas d'échec?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Merci pour ta réponse,

    avec la ligne suivante, ça passe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef LONG (WINAPI *SCardEstablishContextfuncptr) (

  4. #4
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Tout se passe bien maintenant jusqu'à l'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM,NULL,NULL,&hctx);
    qui me génère l'erreur
    Exception non gérée à 0x004157f4 dans ACR38.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000000.
    C'est précisément en effectuant le return dans la fonction suivante que ça plante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SCardEstablishContextfuncptr SCardEstablishContextfp;
    LONG WINAPI SCardEstablishContext (
      __in DWORD dwScope,
      __in LPCVOID pvReserved1,
      __in LPCVOID pvReserved2,
      __out LPSCARDCONTEXT phContext){
        return (SCardEstablishContextfp) (dwScope, pvReserved1, pvReserved2, phContext);
      }

  5. #5
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Ensuite, ne serait-il pas plus simple de lier "implicitement" à la DLL, vu que ton programme la charge directement par nom et quitte en cas d'échec?
    Je viens de regarder ce que signifiait liaison implicite. Je crois avoir compris qu'il fallait posséder un fichier .lib. Or je n'en connais aucun pour winscard.dll.

    Sinon, j'ai essayé de charger la Dll directement dans la fonction main et ça marche
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include "stdafx.h"
    #include <winscard.h>
    
    
    typedef int (__stdcall *MYDLLFUNC)(
      __in   DWORD dwScope,
      __in   LPCVOID pvReserved1,
      __in   LPCVOID pvReserved2,
      __out  LPSCARDCONTEXT phContext);
    
    
    int _tmain(int argc, TCHAR* argv[])
    {
        HINSTANCE hinstDLL;
        MYDLLFUNC ImpFuncDLL;
        long iRet;
        SCARDCONTEXT hSC;
    
        if (hinstDLL=LoadLibrary(_T("winscard.dll"))) {
            ImpFuncDLL = (MYDLLFUNC)GetProcAddress(hinstDLL, "SCardEstablishContext");
            if (ImpFuncDLL) {
                iRet = ImpFuncDLL(SCARD_SCOPE_USER,NULL,NULL,&hSC);
            }
            FreeLibrary(hinstDLL);
        }
    
        return 0;
    }
    C'est pourtant sensiblement la même chose, mais en moins pratique car je ne peux pas appeler les fonctions de la DLL en dehors du main.

    Alors pourquoi l'autre programme plante-t-il?

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 376
    Points : 41 544
    Points
    41 544
    Par défaut
    Je viens de regarder ce que signifiait liaison implicite. Je crois avoir compris qu'il fallait posséder un fichier .lib. Or je n'en connais aucun pour winscard.dll.
    Ah, OK. Dommage.

    Cette ligne est suspecte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SCardEstablishContextfp = (SCardEstablishContextfuncptr)(hLib1, "SCardEstablishContext");
    Je suis même surpris qu'elle compile. Il manque le nom de la fonction GetProcAddress...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Je suis même surpris qu'elle compile. Il manque le nom de la fonction GetProcAddress...
    Oui, encore bien vu. Mais GetProcAddress était bien présent au moment de la compil. J'ai dû l'effacer par mégarde à force de modifs.

    Finalement je viens de résoudre le problème. J'étais un peu paumé dans les WINAPI, les pointeurs de fonction et je n'ai pas vu un truc évident: en voulant conserver le nom de la fonction originale de la DLL, SCardEstablishContext en l'occurrence, j'entrais en conflit avec le prototype déclaré dans winscard.h.

    En changeant de nom, tout est renté dans l'ordre.

    Je vais réfléchir à un moyen de pouvoir appeler cette fonction avec son vrai nom.

    Merci encore pour ton intervention

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Erreur lors d'appel fonction DLL
    Par Sjeuil dans le forum API, COM et SDKs
    Réponses: 8
    Dernier message: 18/09/2014, 10h48
  2. Réponses: 1
    Dernier message: 18/09/2009, 11h25
  3. Pb syntaxe appel fonction DLL
    Par kimlee dans le forum C++
    Réponses: 4
    Dernier message: 04/10/2007, 15h05
  4. PB pour Appel fonction dans DLL sur Builder3
    Par Fbartolo dans le forum C++Builder
    Réponses: 15
    Dernier message: 10/03/2005, 12h58
  5. Appels fonctions DLL
    Par Micka91 dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 17/02/2004, 17h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo