Erreur d'exécution après chargement dll

cs_Cako19 Messages postés 56 Date d'inscription mardi 4 février 2003 Statut Membre Dernière intervention 5 décembre 2005 - 13 avril 2004 à 16:04
cs_fabrice91 Messages postés 27 Date d'inscription jeudi 13 avril 2006 Statut Membre Dernière intervention 28 janvier 2009 - 16 janv. 2009 à 09:49
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

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
13 avril 2004 à 16:11
verif si DLL exporte en __stdcall ou __cdecl, erreur vient de la.

ciao...
BruNews, Admin CS, MVP Visual C++
0
cs_Cako19 Messages postés 56 Date d'inscription mardi 4 février 2003 Statut Membre Dernière intervention 5 décembre 2005
13 avril 2004 à 17:13
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
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
13 avril 2004 à 17:25
CALLBACK et WINAPI est rigoureusement identique, alias de __stdcall.

Essaie avec __cdecl*.

ciao...
BruNews, Admin CS, MVP Visual C++
0
cs_Cako19 Messages postés 56 Date d'inscription mardi 4 février 2003 Statut Membre Dernière intervention 5 décembre 2005
13 avril 2004 à 17:52
C'était ça !! MERCI beaucoup !!!! :big)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_fabrice91 Messages postés 27 Date d'inscription jeudi 13 avril 2006 Statut Membre Dernière intervention 28 janvier 2009
15 janv. 2009 à 10:56
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)
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 janv. 2009 à 15:08
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++
0
cs_fabrice91 Messages postés 27 Date d'inscription jeudi 13 avril 2006 Statut Membre Dernière intervention 28 janvier 2009
15 janv. 2009 à 18:11
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
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
15 janv. 2009 à 19:37
Je n'utilise que VS (rien de tel qu'un outil MS pour compiler pour MS).

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

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

Fonctionne sous code::blocks

C++ (@++)<!--
0
cs_fabrice91 Messages postés 27 Date d'inscription jeudi 13 avril 2006 Statut Membre Dernière intervention 28 janvier 2009
16 janv. 2009 à 09:49
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!
0
Rejoignez-nous