Erreur d'exécution après chargement dll

Signaler
Messages postés
56
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
5 décembre 2005
-
Messages postés
27
Date d'inscription
jeudi 13 avril 2006
Statut
Membre
Dernière intervention
28 janvier 2009
-
Bonjour,

Après avoir défini une fonction appartenant à une dll externe à mon projet, à l'aide de typedef, LoadLibrary, GetProcAdress et etc..., à l'exécution, la fonction que j'utilise renvoie le bon resultat mais donne l'erreur suivante:

"The value of ESP was not properly saved across a fonction call. This is usually a result of calling a fonction declared with one calling convention with a fonction pointer declared with a different calling convention."

Pourtant je suis sure d'avoir bien défini le pointeur de fonction avec les mêmes type de paramètres que la fonction de la dll.

Quelqu'un a t il déjà rencontré cette erreur ou aurait il une idée pour la résoudre ?

Merci d'avance pour votre aide.

Cako19

10 réponses

Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
verif si DLL exporte en __stdcall ou __cdecl, erreur vient de la.

ciao...
BruNews, Admin CS, MVP Visual C++
Messages postés
56
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
5 décembre 2005

la dll exporte en __cdeclspec. Mais que dois je changer pour ne plus avoir l'erreur stp ?

Sachant que là, je mets :

typedef BOOL (CALLBACK* SHA1SURFICHIER)( char*, char*, char*, unsigned long* );

mais que si je mets:
typedef BOOL (WINAPI* SHA1SURFICHIER)( char*, char*, char*, unsigned long* );

Ca me fait l'erreur quand même.

Merci en tout cas d'avoir répondu.

Cako19
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
CALLBACK et WINAPI est rigoureusement identique, alias de __stdcall.

Essaie avec __cdecl*.

ciao...
BruNews, Admin CS, MVP Visual C++
Messages postés
56
Date d'inscription
mardi 4 février 2003
Statut
Membre
Dernière intervention
5 décembre 2005

C'était ça !! MERCI beaucoup !!!! :big)
Messages postés
27
Date d'inscription
jeudi 13 avril 2006
Statut
Membre
Dernière intervention
28 janvier 2009

Salut,
J'ai un problème qui ressemble à celui de ce sujet : j'ai créé une dll (à partir de fonction qui marchent sans problème) qui compile sans aucune erreur, et lorsque je l'utilise elle fait planter mon .exe. Je suis sur de mon .exe, et les fonctions marche parfaitement (je les ai essayé avant dans un projet sans dll). La dll exporte en __declspec , j'ai essayé avec __cdecl, mais lors de la compilation j'ai eu : error: expected initializer before "OpenCOM" j'ai essayé __cdeclspec, mais làerror: `dllimport' was not declared in this scope.  (je suis sous code::block)
Que faire...

Merci d'avance pour l'aide que vous pourrez (j'espère) m'apporter.

Voila mon header :
#ifndef __dllFAB_pointeur_H__
#define __dllFAB_pointeur_H__
#define DllImport   __declspec(dllimport)

#include <windows.h>

BOOL DllImport OpenCOM (HANDLE *g_hCOM, int nId);
BOOL DllImport CloseCOM (HANDLE *g_hCOM);
BOOL DllImport ReadCOM (HANDLE *g_hCOM, void* buffer, int nBytesToRead, int* pBytesRead);
BOOL DllImport WriteCOM (HANDLE *g_hCOM, void* buffer, int nBytesToWrite, int* pBytesWritten);

#endif

et mon code :

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "dllFAB_pointeur.h"
/*  Définition de constantes*/
#define RX_SIZE         4096    /* taille tampon d'entrée  */
#define TX_SIZE         4096    /* taille tampon de sortie */
#define MAX_WAIT_READ   5000    /* temps max d'attente pour lecture (en ms) */
#define DllExport   __declspec(dllexport)

/******************************************************************************
  OpenCOM : ouverture et configuration du port COM.
  entrée : nId : Id du port COM à ouvrir.
  retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL DllExport OpenCOM(HANDLE *g_hCOM, int nId)
{
    /* variables locales */
    char szCOM[16];
    /* Délais d'attente sur le port COM */
    COMMTIMEOUTS g_cto =
    {
        MAX_WAIT_READ,  /* ReadIntervalTimeOut          */
        0,              /* ReadTotalTimeOutMultiplier   */
        MAX_WAIT_READ,  /* ReadTotalTimeOutConstant     */
        0,              /* WriteTotalTimeOutMultiplier  */
        0               /* WriteTotalTimeOutConstant    */
    };

    /* Configuration du port COM */
    DCB g_dcb =
    {
        sizeof(DCB),        /* DCBlength            */
        9600,               /* BaudRate             */
        TRUE,               /* fBinary              */
        FALSE,              /* fParity              */
        FALSE,              /* fOutxCtsFlow         */
        FALSE,              /* fOutxDsrFlow         */
        DTR_CONTROL_ENABLE, /* fDtrControl          */
        FALSE,              /* fDsrSensitivity      */
        FALSE,              /* fTXContinueOnXoff    */
        FALSE,              /* fOutX                */
        FALSE,              /* fInX                 */
        FALSE,              /* fErrorChar           */
        FALSE,              /* fNull                */
        RTS_CONTROL_ENABLE, /* fRtsControl          */
        FALSE,              /* fAbortOnError        */
        0,                  /* fDummy2              */
        0,                  /* wReserved            */
        0x100,              /* XonLim               */
        0x100,              /* XoffLim              */
        8,                  /* ByteSize             */
        NOPARITY,           /* Parity               */
        ONESTOPBIT,         /* StopBits             */
        0x11,               /* XonChar              */
        0x13,               /* XoffChar             */
        '?',                /* ErrorChar            */
        0x1A,               /* EofChar              */
        0x10                /* EvtChar              */
    };

    /* construction du nom du port, tentative d'ouverture */
    sprintf(szCOM, "COM%d", nId);
    *g_hCOM = (HANDLE)CreateFile(szCOM, GENERIC_READ|GENERIC_WRITE, 0, NULL,
                        OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
    if(*g_hCOM == INVALID_HANDLE_VALUE)
    {
        printf("Erreur lors de l'ouverture du port COM%d", nId);
        return FALSE;
    }

    /* affectation taille des tampons d'émission et de réception */
    SetupComm(*g_hCOM, RX_SIZE, TX_SIZE);
    /* configuration du port COM */
    if(!SetCommTimeouts(*g_hCOM, &g_cto) || !SetCommState(*g_hCOM, &g_dcb))
    {
        printf("Erreur lors de la configuration du port COM%d", nId);
        CloseHandle(*g_hCOM);
        return FALSE;
    }

    /* on vide les tampons d'émission et de réception, mise à 1 DTR */
    PurgeComm(*g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
    EscapeCommFunction(*g_hCOM, SETDTR);
    return TRUE;
}

/******************************************************************************
  CloseCOM : fermeture du port COM.
  retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL DllExport CloseCOM(HANDLE *g_hCOM)
{
    /* fermeture du port COM */
    CloseHandle(*g_hCOM);
    return TRUE;
}

/******************************************************************************
  ReadCOM : lecture de données sur le port COM.
  entrée : buffer       : buffer où mettre les données lues.
           nBytesToRead : nombre max d'octets à lire.
           pBytesRead   : variable qui va recevoir le nombre d'octets lus.
  retour : vrai si l'opération a réussi, faux sinon.
-------------------------------------------------------------------------------
  Remarques : - la constante MAX_WAIT_READ utilisée dans la structure
                COMMTIMEOUTS permet de limiter le temps d'attente si aucun
                caractères n'est présent dans le tampon d'entrée.
              - la fonction peut donc retourner vrai sans avoir lu de données.
******************************************************************************/
BOOL DllExport ReadCOM(HANDLE *g_hCOM, void* buffer, int nBytesToRead, int* pBytesRead)
{
    return ReadFile(*g_hCOM, buffer, nBytesToRead, (DWORD*)pBytesRead, NULL);
}

/******************************************************************************
  WriteCOM : envoi de données sur le port COM.
  entrée : buffer        : buffer avec les données à envoyer.
           nBytesToWrite : nombre d'octets à envoyer.
           pBytesWritten : variable qui va recevoir le nombre d'octets
                           envoyés.
  retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL DllExport WriteCOM(HANDLE *g_hCOM, void* buffer, int nBytesToWrite, int* pBytesWritten)
{
    /* écriture sur le port */
    return WriteFile(*g_hCOM, buffer, nBytesToWrite, (DWORD*)pBytesWritten, NULL);

}

BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;

case DLL_PROCESS_DETACH:
break;

case DLL_THREAD_ATTACH:
break;

case DLL_THREAD_DETACH:
break;
}

/* Returns TRUE on success, FALSE on failure */
return TRUE;
}

PS: les fonctions doivent permettre de dialoguer avec un port COM (l'ouvrir, ecrire dessus, le lire et le fermer)
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
Prenez l'habitude de TOUJOURS compiler en stdcall (à régler dans les options du proj sur VS), que soit pour DLL ou EXE et vous n'aurez jamais de problème, c'est le standard sous Windows 32 bits. Ainsi il n'y aura plus à préciser le modèle devant les fonctions.
Pour Windows  64, c'est fastcall le standard.

ciao...
BruNews, MVP VC++
Messages postés
27
Date d'inscription
jeudi 13 avril 2006
Statut
Membre
Dernière intervention
28 janvier 2009

Merci BruNews pour ta réponse, cependant je suis sous code::block et je n'ai pas trouvé cette option dans les propriétés de mon projet...Connais-tu code::block?

Peut-on simplement dans le code modifier cela (j'ai essayé de remplacer #define DllExport   __declspec(dllexport) par #define DllExport   __stdcall(dllexport) ou encore #define DllExport   __cdecl(dllexport)) mais j'ai erreur sur erreur)?
Sais tu ce que je pourrai essayer d'autre, et comment expliquer qu'une dll que j'ai fait précedement (exporté en __declspec) fonctionne correctement et celle la compile bien mais ne fonctionne pas ?!

Encore merci de m'aider dans ce pb
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
Je n'utilise que VS (rien de tel qu'un outil MS pour compiler pour MS).

ciao...
BruNews, MVP VC++
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
Pour exportation:
__declspec(dllexport) void __stdcall fonctionx () {
   //blablabla
}

Puis pour importation (le prototype):
__declspec(dllimport) void __stdcall fonctionx();

Fonctionne sous code::blocks

C++ (@++)<!--
Messages postés
27
Date d'inscription
jeudi 13 avril 2006
Statut
Membre
Dernière intervention
28 janvier 2009

J'ai essayé ton modèle SAKingdom et malheureusement, tjs le mm problème, la librairie compile bien mais lors de l'exécution j'ai tjs la mm erreur windows.. j'ai mm essayé le modèle sur une librairie quasi identique, et cette erreur que je n'avais pas est apparue...:(  Je  vous met le code de la librairie qui fonctionne, cela vous permettra peut etre de voir ou est l'erreur qui m'echappe... d'ailleur celle-ci n'est finalement peut etre pas sur l'exportation (et donc l'importation...)

dll (qui fonctionne) :

header :
#ifndef __dllFAB_H__
#define __dllFAB_H__
#define DllImport   __declspec(dllimport)

#include <windows.h>

BOOL DllImport OpenCOM(int nId);
BOOL DllImport CloseCOM();
BOOL DllImport ReadCOM(void* buffer, int nBytesToRead, int* pBytesRead);
BOOL DllImport WriteCOM(void* buffer, int nBytesToWrite, int* pBytesWritten);

#endif

source :

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "dllFAB.h"
/*  Définition de constantes*/
#define RX_SIZE         4096    /* taille tampon d'entrée  */
#define TX_SIZE         4096    /* taille tampon de sortie */
#define MAX_WAIT_READ   5000    /* temps max d'attente pour lecture (en ms) */
#define DllExport   __declspec(dllexport)
/*  Variables globales.*/

/* Handle du port COM ouvert */
HANDLE g_hCOM = NULL;

/* Délais d'attente sur le port COM */
COMMTIMEOUTS g_cto =
{
    MAX_WAIT_READ,  /* ReadIntervalTimeOut          */
    0,              /* ReadTotalTimeOutMultiplier   */
    MAX_WAIT_READ,  /* ReadTotalTimeOutConstant     */
    0,              /* WriteTotalTimeOutMultiplier  */
    0               /* WriteTotalTimeOutConstant    */
};

/* Configuration du port COM */
DCB g_dcb =
{
    sizeof(DCB),        /* DCBlength            */
    9600,               /* BaudRate             */
    TRUE,               /* fBinary              */
    FALSE,              /* fParity              */
    FALSE,              /* fOutxCtsFlow         */
    FALSE,              /* fOutxDsrFlow         */
    DTR_CONTROL_ENABLE, /* fDtrControl          */
    FALSE,              /* fDsrSensitivity      */
    FALSE,              /* fTXContinueOnXoff    */
    FALSE,              /* fOutX                */
    FALSE,              /* fInX                 */
    FALSE,              /* fErrorChar           */
    FALSE,              /* fNull                */
    RTS_CONTROL_ENABLE, /* fRtsControl          */
    FALSE,              /* fAbortOnError        */
    0,                  /* fDummy2              */
    0,                  /* wReserved            */
    0x100,              /* XonLim               */
    0x100,              /* XoffLim              */
    8,                  /* ByteSize             */
    NOPARITY,           /* Parity               */
    ONESTOPBIT,         /* StopBits             */
    0x11,               /* XonChar              */
    0x13,               /* XoffChar             */
    '?',                /* ErrorChar            */
    0x1A,               /* EofChar              */
    0x10                /* EvtChar              */
};

/******************************************************************************
  OpenCOM : ouverture et configuration du port COM.
  entrée : nId : Id du port COM à ouvrir.
  retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/

BOOL DllExport OpenCOM(int nId)
{
    /* variables locales */
    char szCOM[16];

    /* construction du nom du port, tentative d'ouverture */
    sprintf(szCOM, "COM%d", nId);
    g_hCOM = CreateFile(szCOM, GENERIC_READ|GENERIC_WRITE, 0, NULL,
                        OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
    if(g_hCOM == INVALID_HANDLE_VALUE)
    {
        printf("Erreur lors de l'ouverture du port COM%d", nId);
        return FALSE;
    }

    /* affectation taille des tampons d'émission et de réception */
    SetupComm(g_hCOM, RX_SIZE, TX_SIZE);

    /* configuration du port COM */
    if(!SetCommTimeouts(g_hCOM, &g_cto) || !SetCommState(g_hCOM, &g_dcb))
    {
        printf("Erreur lors de la configuration du port COM%d", nId);
        CloseHandle(g_hCOM);
        return FALSE;
    }

    /* on vide les tampons d'émission et de réception, mise à 1 DTR */
    PurgeComm(g_hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);
    EscapeCommFunction(g_hCOM, SETDTR);
    return TRUE;
}

/******************************************************************************
  CloseCOM : fermeture du port COM.
  retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL DllExport CloseCOM()
{
    /* fermeture du port COM */
    CloseHandle(g_hCOM);
    return TRUE;
}

/******************************************************************************
  ReadCOM : lecture de données sur le port COM.
  entrée : buffer       : buffer où mettre les données lues.
           nBytesToRead : nombre max d'octets à lire.
           pBytesRead   : variable qui va recevoir le nombre d'octets lus.
  retour : vrai si l'opération a réussi, faux sinon.
-------------------------------------------------------------------------------
  Remarques : - la constante MAX_WAIT_READ utilisée dans la structure
                COMMTIMEOUTS permet de limiter le temps d'attente si aucun
                caractères n'est présent dans le tampon d'entrée.
              - la fonction peut donc retourner vrai sans avoir lu de données.
******************************************************************************/
BOOL DllExport ReadCOM(void* buffer, int nBytesToRead, int* pBytesRead)
{
    /*return ReadFile(g_hCOM, buffer, nBytesToRead, pBytesRead, NULL);*/
    return ReadFile(g_hCOM, buffer, nBytesToRead, (DWORD*)pBytesRead, NULL);/*ajout d'un cast*/
}

/******************************************************************************
  WriteCOM : envoi de données sur le port COM.
  entrée : buffer        : buffer avec les données à envoyer.
           nBytesToWrite : nombre d'octets à envoyer.
           pBytesWritten : variable qui va recevoir le nombre d'octets
                           envoyés.
  retour : vrai si l'opération a réussi, faux sinon.
******************************************************************************/
BOOL DllExport WriteCOM(void* buffer, int nBytesToWrite, int* pBytesWritten)
{
    /* écriture sur le port */
    /*return WriteFile(g_hCOM, buffer, nBytesToWrite, pBytesWritten, NULL);*/
    return WriteFile(g_hCOM, buffer, nBytesToWrite, (DWORD*)pBytesWritten, NULL);

}

BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;

case DLL_PROCESS_DETACH:
break;

case DLL_THREAD_ATTACH:
break;

case DLL_THREAD_DETACH:
break;
}

/* Returns TRUE on success, FALSE on failure */
return TRUE;
}

Vous l'aurez compris, la différence entre les 2 est que le handle du port série avec lequel je eveux dialoguer est placé en argument dans chacune des 4 fonctions.
En tout cas merci de m'aider!