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

C++ Discussion :

Erreur de compilation sur un programme d'interface de port série


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert sécurité informatique

    Informations forums :
    Inscription : Mars 2017
    Messages : 3
    Par défaut Erreur de compilation sur un programme d'interface de port série
    Hello à tous,

    J'ai du migrer un programme C vers un compilateur C++ suite à l'ajout d'une bibliothèque dynamique compiler dans ce dernier.
    Le changement de compilateur me retourne une erreur que je n'avais pas sur un compilateur C.
    Malheureusement je ne maitrise pas le C++, et espère que les fonctions incriminées et le log du compilateur inspirera une âme charitable

    Merci par avance.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    H:\sandbox\test\main.cpp||In function 'BOOL ReadCOM(void*, int, int*)':|
    H:\sandbox\test\main.cpp|207|error: invalid conversion from 'int*' to 'PDWORD {aka long unsigned int*}' [-fpermissive]|
    C:\Program Files (x86)\CodeBlocks\MinGW\include\winbase.h|2012|note: initializing argument 4 of 'BOOL ReadFile(HANDLE, PVOID, DWORD, PDWORD, LPOVERLAPPED)'|
     
    H:\sandbox\test\main.cpp||In function 'BOOL WriteCOM(void*, int, int*)':|
    H:\sandbox\test\main.cpp|221|error: invalid conversion from 'int*' to 'PDWORD {aka long unsigned int*}' [-fpermissive]|
    C:\Program Files (x86)\CodeBlocks\MinGW\include\winbase.h|2206|note: initializing argument 4 of 'BOOL WriteFile(HANDLE, PCVOID, DWORD, PDWORD, LPOVERLAPPED)'|

    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
     
     
    BOOL ReadCOM    (void* buffer, int nBytesToRead, int* pBytesRead);
    BOOL WriteCOM   (void* buffer, int nBytesToWrite, int* pBytesWritten);
     
     
    BOOL ReadCOM(void* buffer, int nBytesToRead, int* pBytesRead)
    {
        return ReadFile(g_hCOM, buffer, nBytesToRead, pBytesRead, NULL);
    }
     
     
    BOOL WriteCOM(void* buffer, int nBytesToWrite, int* pBytesWritten)
    {
        /* écriture sur le port */
        return WriteFile(g_hCOM, buffer, nBytesToWrite, pBytesWritten, NULL);
    }

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 482
    Par défaut
    Laissez-moi vous dire qu'un éditeur/développeur qui force le passage d'une API C à une "API" C++, moi, j'appelle cela un gros guignol.
    Les API C++, c'est tellement merdique actuellement (le draft du standard C++17 à encore repousser sa standardisation, snif) que passer d'une API C à une "API" C++ n'a aucun de putain de sens.

    On va faire l'abstraction de cette connerie et faire ça comme un petit exercice "à la con".

    Votre code, c'est clairement du code C et pas du code C++ :
    - pas de typedef BOOL tout moisi mais l'utilisation du type intégré bool.
    - renvoyer un BOOL au lieu de renvoyer la chaine lue pour la fonction "ReadCOM"
    - Utilisation d'un code retour pour gérer des erreurs et pas d'utilisation d'exceptions
    - Utilisation de pointeur à la place de références pour les paramètres
    - etc...

    On ne va pas faire du C++, on va essayer de rendre votre code C compilable dans un compilateur C++.
    OK ?

    Votre code C ne compile pas en C++ car le compilateur C++ est beaucoup plus tatillon que votre compilateur C, semble-t-il.
    Mais l'erreur, elle existe, aussi bien en C qu'en C++.

    Vous passez aux fonctions Win32 ReadFile et WriteFile (qui sont des API C et pas C++ au demeurant), en 4ème paramètre un "int*" et pas un "PDWORD".
    Avec les options de compilation actuels "PDWORD" est égale à "long unsigned int*".
    Donc, si voulez que le compilateur ne vous engueule plus, ne passez pas un "int*" mais un "long unsigned int*".
    Mais dès que vous allez changer d'options de compilation, ça va être encore la foire à saucisse.
    Donc, soit vos fonctions "ReadCOM"/WriteCOM sont de simple wrapper "fin" sur l'API Win32 et vous utiliser les mêmes signatures que les primitives de bases :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    BOOL ReadCOM(LPVOID buffer, DWORD nBytesToRead, LPDWORD pBytesRead)
    {
        return ReadFile(g_hCOM, buffer, nBytesToRead, pBytesRead, NULL);
    }
     
     
    BOOL WriteCOM(LPVOID buffer, DWORD nBytesToWrite, LPDWORD pBytesWritten)
    {
        /* écriture sur le port */
        return WriteFile(g_hCOM, buffer, nBytesToWrite, pBytesWritten, NULL);
    }
    Soit vous en faite de "vraies" fonctions qui doivent vraiment s'occuper du transtypage de ses paramètres avant de les passer en argument des primitives Win32 ("gestion" des paramètres négatifs via assert, etc...).
    Quitte à faire ce travail de transtypage, pensez à utiliser toutes les fonctionnalités qu'offre le C++ comme les exceptions, les conversions implicites et explicites, les classes de la STL comme std::string ou std::vector<>, etc...

    P.S.: "g_hCOM", les globales, c'est CACA.

  3. #3
    Candidat au Club
    Homme Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert sécurité informatique

    Informations forums :
    Inscription : Mars 2017
    Messages : 3
    Par défaut
    Merci beaucoup d'avoir pris le temps de me répondre.
    Je reconnais bien mon incompétence en C++ et vais m'y mettre sérieusement, je code principalement pour des microcontroleurs.
    J'avais déjà essayé de corriger la signature des fonctions avec LPDWORD en lieu et place du int* mais sans succès m'ouvrant une autre erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    main.obj||error LNK2019: symbole externe non résolu "int __cdecl ReadCOM(void *,int,int *)" (?ReadCOM@@YAHPAXHPAH@Z) référencé dans la fonction _main|
    main.obj||error LNK2019: symbole externe non résolu "int __cdecl WriteCOM(void *,int,int *)" (?WriteCOM@@YAHPAXHPAH@Z) référencé dans la fonction _main|
    bin\Release\mes_tests.exe||fatal error LNK1120: 2 externes non résolus|
    ||=== Build failed: 3 error(s), 6 warning(s) (0 minute(s), 0 second(s)) ===|
    J'ai trouvé une classe C++ sur le site de developpez.net, je vais me rabattre sur cette solution même si à première vue elle utilise aussi l'API Win32
    https://cpp.developpez.com/faq/vc?pa...Communications

    Merci pour votre aide et vos explications.

    P.S : Autant pour moi je n'avais pas mis à jour tous les symboles, le code fonctionne. Merci !

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 482
    Par défaut
    Je reconnais bien mon incompétence en C++
    Pas de problème, Rome ne s'est pas faite en 1 jour.
    Mais c'est bien de savoir qu'on n'est pas encore arrivé.

    fonctions avec LPDWORD en lieu et place du int* mais sans succès m'ouvrant une autre erreur.
    L'erreur, ici, est une erreur de link.
    Le message d'erreur indique ce que le linker n'a pas trouvé dans les .obj et .lib qu'on lui à donné.
    Aux noms des fonctions nom trouvées ("int __cdecl ReadCOM(void *,int,int *)" et "int __cdecl WriteCOM(void *,int,int *)"), il cherche les fonctions avec les anciennes signatures ( "int*" en 3ème paramètre et pas "long unsigned int*" pour LPDWORD ), c'est des choses qui devrait être dans les .obj généré.
    Il y a donc discordance entre les .h et les .cpp.
    le "int" devant "int __cdecl ReadCOM(void *,int,int *)", c'est le "vrai" BOOL, sans la ruse des MACRO.
    "int __cdecl ReadCOM(void *,int,int *)", c'est pour indiquer que la fonction utilise les conventions d'appel à la "C", et pas les conventions d'appel "standard" de Windows.
    "int __cdecl ReadCOM(void *,int,int *)", c'est le nom de la fonction.
    "int __cdecl ReadCOM(void *,int,int *)", c'est le LPVOID du 1er paramètre de la fonction, normalement.
    "int __cdecl ReadCOM(void *,int,int *)", c'est le DWORD du 2ème paramètre de la fonction, normalement, mais c'est bizarre si la compilation est en 64bits.
    "int __cdecl ReadCOM(void *,int,int *)", c'est le LPDWORD du 3ème paramètre de la fonction, normalement, mais c'est bizarre si la compilation est comme celle d'avant qui attendait un "long unsigned int*".

    Les cas les plus classiques de "discordance" entre les .h et les .cpp, c'est que la signature dans le Cpp n'est pas la même que dans le .h.
    Si vous utilisez maladroitement les pre-compiled headers (stdAfx.h), il peut aussi avoir désynchronisation entre le .h et ce que le compilateur utilise (il utilise une vielle version du .h).
    P.S : Autant pour moi je n'avais pas mis à jour tous les symboles, le code fonctionne. Merci !
    On parle donc d'un problème de pre-compiled headers ?
    Parce que "symboles", c'est assez flou pour moi, ailleurs que dans les informations de débug.

    si à première vue elle utilise aussi l'API Win32
    C'est l'API standard de Windows (ou presque, parce que les API OS/2 ou POSIX de Windows, c'est vraiment du foutage de gueule), donc, soit elle est utilisé directement ou c'est une bibliothèque qui l'utilise et vous utilisez cette bibliothèque.
    Vous utiliserez donc forcément Win32 soit directement soit indirectement.

    L'exemple que vous montrez est bien un wrapping "lourd" qui utilise les fonctionnalités du C++ pour simplifier grandement l'utilisation d'un port COM, même dans des situations complexes.

    C'est le genre d'outil qui vous fait gagner beaucoup de temps.
    Mais cette classe utilise des archaïsmes comme des "return -1" en cas d'erreur, etc...
    Ça sent le programmeur C qui s'est essayé au C++ ou un programmeur C++ qui a fait une API C++ mais avec pas mal de C dedans pour pas trop perdre d'utilisateur C.
    Attention aussi qu'il utilise des trucs comme "AfxMessageBox" ou "CString" qui ne sont disponible qu'avec MFC, une surcouche à Win32.

    Donc, utilisez là pour gagner du temps, mais ne vous en servez pas comme exemple de conception d'une classe C++.

  5. #5
    Candidat au Club
    Homme Profil pro
    Expert sécurité informatique
    Inscrit en
    Mars 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert sécurité informatique

    Informations forums :
    Inscription : Mars 2017
    Messages : 3
    Par défaut
    Un grand merci pour ces précisions, puisse un jour avoir les mêmes connaissances.
    Vous avez vu juste c'est une mauvaise manipulation des pre-compiled headers qui est à l'origine de la deuxième erreur.
    C'est pourtant une erreur de base, j'aurais du trouver et résoudre le problème de suite, comme vous le dites le chemin est encore long
    Encore merci d'avoir pris le temps de développer vos réponses c'est appréciable, elles ont été lues religieusement.

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

Discussions similaires

  1. aide sur une erreur apres compilation d'un programme
    Par oscarus dans le forum Dev-C++
    Réponses: 0
    Dernier message: 04/02/2014, 20h08
  2. Réponses: 11
    Dernier message: 17/09/2011, 17h25
  3. Erreur de compilation sur gaim-vv avec gstrreamer
    Par ZiMo dans le forum Applications et environnements graphiques
    Réponses: 1
    Dernier message: 30/12/2005, 10h41
  4. Erreur à la compile sur VC++ 6
    Par norwy dans le forum Développement
    Réponses: 1
    Dernier message: 10/11/2005, 13h51
  5. Delphi 7 update 1 - Erreur de compil sur SQLExpr
    Par RamDevTeam dans le forum Bases de données
    Réponses: 14
    Dernier message: 02/11/2005, 17h44

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