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

Langage Delphi Discussion :

Traduction de C en Pascal sous Delphi 10.2


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Inscrit en
    Mars 2002
    Messages
    240
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 240
    Points : 102
    Points
    102
    Par défaut Traduction de C en Pascal sous Delphi 10.2
    j'ai dû traduire du code C d'une partie de fichiers .h et .cpp en code Pascal (sous Delphi 10.2) pour appeler une dll. Malheureusement ça ne fonctionne pas ! Sur quel forum je peux poster cette traduction manuelle car 2 questions se posent :
    - la traduction faite des types et structures de C vers Pascal est elle correcte ?
    - la traduction faite de l'appel de la méthode is_ImageFile() de C vers Pascal est elle correcte ?
    merci

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Ici cela semble approprié, en tout cas plus que sur un Forum C, si un Développeur Delphi a des notions de C, la réciproque est rarissime.
    J'ai du faire aussi ce travail, c'est assez fréquent pour l'utilisation d'API

    Tu as des .cpp pour appeler une DLL ? curieux, tu as rare de code fourni (ou alors un exemple voire un rarissime wrapper)
    en général, tu n'as que le .h qui défini les types

    Important, ajoute un lien vers la documentation de la DLL, ça peut aider et si cela devient trop chaud, c'est au fabricant qu'il faudra demander de l'aide

  3. #3
    Membre régulier
    Inscrit en
    Mars 2002
    Messages
    240
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 240
    Points : 102
    Points
    102
    Par défaut
    tu as raison concernant le fichier .cpp : c'est juste un exemple de code fourni qui fonctionne lors de l'appel de la fonction is_ImageFile(). J'ai utilisé cet exemple pour traduire en Pascal l'appel de cette même fonction qui se trouve dans un dll. Le fichier .h me fournit les définitions des struct et signatures des fonctions en C à traduire également en Pascal. Jusqu'en 2014 le fournisseur de la dll fournissait également un fichier .pas "équivalent" au fichier .h mais depuis ce n'est plus le cas. Aujourd'hui je bloque sur une struct et l'appel à une fonction is_ImageFile() définies dans le nouveau .h => ça compile mais l'exécution plante en 32 ou 64 bits Windows.

    voici pour ceux qui sont motivés les bouts de code en C et leur traduction en Pascal :

    *******************************************
    *1-le code en C fourni par l'éditeur :*
    *******************************************
    //------------------------- dans unfichier.h -------------------------
    Code C : 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
     
    #define IS_IMG_BMP                          0
    #define IS_IMG_JPG                          1
     
    typedef DWORD   HIDS;
    #define HIDS_DEFINED
     
    #define IDSEXP    INT
     
    typedef struct
    {
        wchar_t* pwchFileName;
        UINT     nFileType;
        UINT     nQuality;
        char**   ppcImageMem;
        UINT*    pnImageID;
        BYTE     reserved[32];
     
    } IMAGE_FILE_PARAMS;
     
     
    /*!
     * \brief Enumeration of commands of function \ref is_ImageFile,
     *
     * \sa is_ImageFile.
     */
    typedef enum E_IMAGE_FILE_CMD
    {
        IS_IMAGE_FILE_CMD_LOAD    = 1,
        IS_IMAGE_FILE_CMD_SAVE    = 2
     
    } IMAGE_FILE_CMD;
     
    /*!
    * \brief Interface for all image file operations
    * \param   hCam            valid device handle.
    * \param   nCommand        Specifies the command
    * \param   pParam          input or output storage for the accessed param.
    * \param   cbSizeOfParam   size of *pParam.
    * \return  error code
    */
    IDSEXP is_ImageFile(HIDS hCam, UINT nCommand, void* pParam, UINT cbSizeOfParam);
    ***************************************
    *2-traduction dans Delphi 10.2 Tokyo :*
    ***************************************

    //------------------------- dans unfichier.pas -------------------------
    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
     
        HIDS           = THandle;  
     
        IS_IMAGE_FILE_CMD_LOAD = 1;
        IS_IMAGE_FILE_CMD_SAVE = 2;
     
        IS_IMG_BMP = 0;
        IS_IMG_JPG = 1;	
     
        PPByte = ^PByte;
        PIMAGE_FILE_PARAMS = ^IMAGE_FILE_PARAMS;
     
        IMAGE_FILE_PARAMS = packed record
            pwchFileName: PWideChar;
            nFileType: Longword;//UINT;
            nQuality: Longword;//UINT;
            ppcImageMem: PPByte;//PPChar;
            pnImageID: PLongword;//PUINT;
            reserved: packed array [0..31] of Byte library;
        end;
     
    function is_ImageFile            (hF:           HIDS;
                                      Command:      Longword;
                                      var Param;
                                      ParamSize:    Longword):  Longint; cdecl;
     
    // Pour charger la méthode depuis la DLL (en C)
    function is_ImageFile
           (hF:           HIDS;
            Command:      Longword;
            var Param;
            ParamSize:    Longword):
            {result}Longint;                 external Driver_DLL_Name;
    ***********************************************************
    3-exemple de code en C appelant la méthode is_ImageFile() et qui fonctionne:*
    ***********************************************************

    //------------------------- dans autrefichier.cpp -------------------------
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    IMAGE_FILE_PARAMS ImageFileParams;
     
    ImageFileParams.pwchFileName = L"c:\\test.bmp";
    ImageFileParams.pnImageID = NULL;
    ImageFileParams.ppcImageMem = NULL;
    ImageFileParams.nQuality = 0; 
     
    // Save bitmap from active memory to file
     
    ImageFileParams.nFileType = IS_IMG_BMP;
     
    INT nRet = is_ImageFile(m_hCam, IS_IMAGE_FILE_CMD_SAVE, (void*)&ImageFileParams, sizeof(ImageFileParams));
    ************************************************************************
    4-traduction dans Delphi 10.2 Tokyo appelant la méthode is_ImageFile():*
    ************************************************************************

    //------------------------- dans autrefichier.pas -------------------------
    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
     
    var
        ImageFileParams: IMAGE_FILE_PARAMS;
        Ptr: Pointer;
        Res: Longint;
        fileName: string;
    begin
        fileName := ExtractFilePath(ParamStr(0)) + 'test.bmp';
        ImageFileParams.pwchFileName := PWideChar(fileName);
        ImageFileParams.pnImageID := nil;
        ImageFileParams.ppcImageMem := nil;
        ImageFileParams.nQuality := 0;
        ImageFileParams.nFileType := IS_IMG_BMP;
        Ptr := @ImageFileParams;
     
        Result := is_ImageFile(f_hCam, IS_IMAGE_FILE_CMD_SAVE, Ptr, sizeof(ImageFileParams)); // génère une erreur à l'éxecution (1)
    (1) en 64 bits : "Error Code=2 Message=An I/O request to the driver failed"
    (1) en 32 bits : "Error Code=-1 Message=An unspecified error occurred"

    Nota: je ne peux pas rajouter un lien vers la doc de la dll car il faut avoir un compte chez eux (éditeur ids-imaging) pour y avoir accès. De plus l'éditeur a clairement indiqué qu'il ne fournira pas d'aide sur ce sujet (la traduction vers Delphi n'étant plus maintenue comme indiquée plus haut)

    Les 2 questions restent ouvertes :
    - la traduction des types et structures de C vers Pascal est elle correcte (voir parties 1 & 2 ci-dessus) ?
    - la traduction de l'appel de la méthode is_ImageFile() de C vers Pascal est elle correcte (voir parties 3 & 4 ci-dessus) ?

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    c'est toujours la même histoire

    1) la conversion d'appel: stdcall ou cdecl en général

    2) la taille des structures: attention à l'alignement !

    3) AnsiChar / (Wide)Char pour les caractères

    le plus simple étant d'avoir un source C compilable qui fonctionne et qui puisse afficher printf("%d\n", sizeof(IMAGE_FILE_PARAMS)); à comparer avec un SizeOf(IMAGE_FILE_PARAMS) sous Delphi.

    il est aussi parfois possible de s'en sortir en déclarant la fonction dans une DLL Delphi et de l'invoquer depuis le programme C, dans le debuger on peut alors s'assurer que les paramètres envoyés par le programme C coïncides avec la structure Pascal.

  5. #5
    Membre régulier
    Inscrit en
    Mars 2002
    Messages
    240
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 240
    Points : 102
    Points
    102
    Par défaut
    merci pour cette réponse. Je vais comparer dès que possible la taille de IMAGE_FILE_PARAMS dans un 1er temps. Pour la 2ème partie (DLL Delphi) je verrai après car je n'ai pas compris le principe et par conséquent comment faire. Je laisse ce post ouvert pour le moment pour faire un retour

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    var Param; je lui préférerais un Param: Pointer question de gout.

    effectivement, packed ce n'est pas obligatoire
    Par exemple, les API Windows sont en {$ALIGN ON}/#pragma pack(push,8).
    Vérifie si c'est le bon alignement comme le suggère Paul TOTH via sizeof
    Le fournisseur de la lib peut au moins te confirmer l'alignement utilisé, cela n'a rien à voir avec Delphi, même en C++, le problème peut se poser

    Pour le THandle, attention, entre 32 et 64bits, ce n'est pas la même chose !
    J'utiliserais un DWORD systématiquement

  7. #7
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par jakouz Voir le message
    merci pour cette réponse. Je vais comparer dès que possible la taille de IMAGE_FILE_PARAMS dans un 1er temps. Pour la 2ème partie (DLL Delphi) je verrai après car je n'ai pas compris le principe et par conséquent comment faire. Je laisse ce post ouvert pour le moment pour faire un retour
    la DLL Delphi, c'est tout simplement inverser le test; j'ai recours à cela quand je ne peux pas compiler le code C mais que j'ai une application existante qui invoque la DLL. Du coup je crée une DLL sous Delphi qui expose les mêmes fonctions que l'originale et je regarde si je parviens bien à lire les paramètres envoyés par l'appli C.

    il est tout à fait possible de s'insérer entre un exe et sa dll, mai ça demande un petit peu de boulot s'il y a beaucoup de fonctions exploitées par l'exe.

    prenons un exemple simple avec 1 seule fonction

    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
     
    library nom_dll;
     
    uses
      Windows; // pour AllocConsole
     
    // ici je pointe sur la DLL originale en C en indiquant son chemin explicitement
    function proc1_original(param: Single): Integer stdcall; external 'c:\windows\system32\nom_dll.dll' name 'proc1';
     
    // en plaçant cette DLL produite par Delphi dans le répertoire de l'exe qui veux invoquer proc1 je peux
    // à la fois intercepter l'appel et faire suivre à la DLL originale
     
    function proc1(param: Single): Integer; stdcall;
    begin
      WriteLn('je suis dans Proc1');
      Result := proc1_original(param);
    end;
     
    exports
      proc1;
     
    begin
      AllocConsole; // pour pouvoir utiliser WriteLn
    end.

Discussions similaires

  1. Comment exécuter un programme en Pascal sous Delphi ?
    Par nadirmabed dans le forum Débuter
    Réponses: 6
    Dernier message: 07/12/2014, 04h18
  2. Ecrire un programme Pascal sous Delphi
    Par moh-23 dans le forum Débuter
    Réponses: 3
    Dernier message: 15/10/2007, 22h59
  3. Traduction d'un logiciel sous Delphi
    Par F6EPT dans le forum Delphi
    Réponses: 16
    Dernier message: 04/02/2007, 23h47
  4. Réponses: 4
    Dernier message: 27/03/2002, 11h03

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