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

Lazarus Pascal Discussion :

Utilisation d'une bibliothèque écrite en C [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut Utilisation d'une bibliothèque écrite en C
    Bonjour,

    J'ai l'impression que l'utilisation avec Lazarus d'une bibliothèque écrite en C/C++ est compliquée.
    Je souhaite utiliser certaines fonctions ou procedures provenant d'une bibliothèque en C/C++.
    J'ai créé une bibliothèque de test (MyLib.lib) que j'ai ajoutée au projet (Projet -> Inspecteur de projet)

    Le code source en C/C++ (fait avec une ancienne version de Borland Builder C++ 6) :
    la bibliothèque est créée avec l'option DLL en C++

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    extern "C" __declspec(dllexport) __cdecl   void  MonTest(char *Msg);
     
    //---------------------------------------------------------------------------
    void  __cdecl  MonTest(char *Msg)
    {
     strcpy(Msg, "Mon premier Test : MyLib.lib");
    }


    Dans Lazarus (2.0.12) : Sur le formulaire, j'ai placé un bouton pour appeler la procédure MonTest :

    la déclaration de la procédure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure MonTest(Msg:String);cdecl;external 'MyLib.lib' name 'MonTest';
     
    // la procedure MonTest() :
    procedure TForm1.Button1Click(Sender: TObject);
    VAR
      s:String;
    begin
       s:='';
      MonTest(s);
      ShowMessage(s);
    end;
    A l'exécution du programme de test :
    j'ai l'erreur suivante :

    Nom : Erreur.png
Affichages : 609
Taille : 9,4 Ko

    Merci pour un conseil de débogage.
    Cordialement

  2. #2
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 353
    Points
    4 353
    Billets dans le blog
    2
    Par défaut
    Bonjour, il faut que tu compiles ta bibliotheque C++ en un fichier DLL compatible avec Windows.

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut
    Bonjour,
    La compilation de la bibliothèque avec Builder C++ 6, a donné deux bibliothèques : une dynamique (.DLL) et une statique (.LIB).
    Ces 2 bibliothèques fonctionnent avec un programme écrit et compilé en C. Mais avec Lazarus non.
    La .DLL ne se charge pas.

  4. #4
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 353
    Points
    4 353
    Billets dans le blog
    2
    Par défaut
    Salut, fait une nouvelle unité juste pour le chargement de ta librairie dynamiquement. Essayes ceci :

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    unit MyLib;
     
    interface
     
    uses
      dynlibs, LCLType;
     
    var
      myLibFilename : string =
      {$if defined(Win32)}
        'MyLib32.dll'
      {$elseif defined(Win64)}
        'MyLib64.dll'
      {$elseif defined(Darwin)}
        'yLib.dylib'
      {$elseif defined(Unix)}
        'MyLib.so'
      {$else}
        ''
      {$endif};
     
    var
     monTest :  procedure MonTest(Msg:String);cdecl;// ou stdcall
     
    var
      myLibHandle: TLibHandle = dynlibs.NilHandle; // this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
      myLibRefCount : cardinal = 0;  // Reference counter
     
    function myLibLoaded : boolean; inline;
    Function myLibLoad(const libfilename:string = ''): boolean; // load the lib
    Procedure myLibUnload; // unload and frees the lib from memory : do not forget to call it before close application.
     
    implementation
     
    uses sysutils;
     
    function myLibLoaded: boolean;
    begin
     Result := (myLibHandle <> dynlibs.NilHandle);
    end;
     
    Function myLibLoad (const libfilename:string) :boolean;
    var
      thelib: string;
    begin
      Result := False;
      if myLibHandle<>0 then
      begin
       Inc(myLibRefCount);
       result:=true {is it already there ?}
      end else
      begin {go & load the library}
        if Length(libfilename) = 0 then
        begin
          thelib := libfilename;
          if thelib = '' then exit(false);
          thelib := ExtractFilePath(ParamStr(0)) + DirectorySeparator + thelib;
        end else thelib := libfilename;
        myLibHandle := DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
        {$IFDEF WINDOWS}
        // second try on Windows without 32/64 suffix
        if myLibHandle = DynLibs.NilHandle then
        begin
          thelib := ExtractFilePath(ParamStr(0)) + DirectorySeparator + 'myLib.dll';
          myLibHandle := DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
        end;
        {$ENDIF}
        if myLibPHandle <> DynLibs.NilHandle then
        begin {now we tie the functions to the VARs from above}
         Pointer(monTest):=DynLibs.GetProcedureAddress(myLibHandle,PChar('MonTest'));
     end;
        Result := myLibLoaded;
        myLibRefCount:=1;
      end;
    end;
     
    Procedure myLibUnload;
    begin
      // < Reference counting
      if myLibRefCount > 0 then dec(myLibRefCount);
      if myLibRefCount > 0 then exit;
     
      if myLibLoaded then
      begin
        DynLibs.UnloadLibrary(myLibHandle);
        myLibHandle := DynLibs.NilHandle;
      end;
    end;
     
    initialization
      myLibLoad(myLibFilename);
    finalization
      myLibUnload;
    end.
    Si cela ne marche, pas c'est peut-être la façon de faire de ton code C++ et comment tu compiles ta DLL (32bit/64bit) qui n'est pas bonne

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut
    Bonjour,
    Excusez moi, j'ai mis du temps pour vous répondre.
    Le problème provenait de l'appel de SetLoadLibrary, je l'ai remplacé par LoadLibrary.

    Avec un programme en C tout fonctionne sans aucun souci, mais avec Lazarus (Freepascal), j'ai toujours des problèmes avec l'information récupérée, Les données ne sont pas correctes.
    La fonction de la DLL accepte 3 arguments : 2 en pointeurs LPSTR et un entier de style :

    function MonTest(var strin:LPSTR; var strout:LPSTR; lng:integer):integer;

    Je fais passer les arguments 1 et 2 en tant PChar les données retournées ne sont cohérentes.

    Je ne trouve pas le moyen pour récupérer la bonne information, je trouve que les variables en C sont plus simples à traiter qu'en Freepascal.
    Je suis passé en Lazarus, car je ne trouve pas l'équivalent de Lazarus mais en langage C.
    Bien cordialement

  6. #6
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 879
    Points : 11 373
    Points
    11 373
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Je me demande si les paramètres ont besoin d'être passés en var et pas en simples PChar.
    En C, le LPSTR est un char*, mais un paramètre var LPSTR n'est-il pas analogue à un *LPSTR, soit un char** ?
    Enfin, le type LPSTR semble être ANSI, UTF-8 ou autre et pouvoir ne pas se terminer par un zéro.
    Par défaut, le PChar de Lazarus est à zéro terminal et UTF-8.

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut
    Bonjour,
    J'ai trouvé le problème mais pas la solution.
    Je crypte une structure (tableau de char et des entiers).
    En C je l'ai fait passer en char *, tout fonctionne bien pour le cryptage et pour décryptage, que ce soit en appelant la fonction de la DLL ou en intégrant la même fonction dans un programme en C/C++.
    En Freepascal, le décryptage n'est pas correct car il y a des champs "integer", quand tous les champs de la structure sont en char le résultat est correct.
    Faut-il inverser les LSB/MSB des champs "integer" en Freepascal avant le cryptage ou après le décryptage ?
    La manipulation de cette structure en Pascal devient compliquée.
    Le cast d'un pointeur PChar en pointeur de structure est-il faisable en Freepascal ?
    Merci
    Cordialement.

  8. #8
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 094
    Points : 1 530
    Points
    1 530
    Billets dans le blog
    5
    Par défaut
    A mon avis tu te compliques la vie.
    Le mieux est de passer des paramètres simples et commun aux 2 langages.
    Il faut aussi faire attention aux conventions d'appel des fonctions dans la DLL
    Je te renvoie à cette discussion (Comportement étrange d'une DLL en fonction de la compilation 32bit ou 64bits ) qui pourra peut être t'éclairer un peu plus.

  9. #9
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 071
    Points : 9 515
    Points
    9 515
    Par défaut
    hello,
    Citation Envoyé par tonton67 Voir le message
    Bonjour,
    J'ai trouvé le problème mais pas la solution.
    Je crypte une structure (tableau de char et des entiers).
    En C je l'ai fait passer en char *, tout fonctionne bien pour le cryptage et pour décryptage, que ce soit en appelant la fonction de la DLL ou en intégrant la même fonction dans un programme en C/C++.
    En Freepascal, le décryptage n'est pas correct car il y a des champs "integer", quand tous les champs de la structure sont en char le résultat est correct.
    Faut-il inverser les LSB/MSB des champs "integer" en Freepascal avant le cryptage ou après le décryptage ?
    La manipulation de cette structure en Pascal devient compliquée.
    Le cast d'un pointeur PChar en pointeur de structure est-il faisable en Freepascal ?
    Merci
    Cordialement.
    Peux-tu nous montrer ton code c ( dépersonnaliser le cryptage,decryptage si confidentiel) , la structure et le code lazarus ?

    Ami calmant, J.P

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut
    Bonjour,
    Je peux publier le code sans problème :

    //**************************************
    j'ai utilisé ce code dans un fichier include au code source
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void Encrypter (char *in, char *out, int lng)
    {
      int i, j;
      for (i = 0; i < lng; i++)  {
          j = (255 - (i & 254)) | (127 ^ i);
          out[i] = in[i] ^ (char)j;
      }
    }
    //**************************************
    ce code est intégré dans une DLL :
    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
    extern "C" __declspec(dllexport) int Encrypter (LPSTR strin, LPSTR strout, int lng)
    {
      int i, j;
      LPSTR p, q;
     
      if (lng > 0) {
            p = (char *)malloc(lng+1);
            if (!p) return -1;
     
            q = (char *)malloc(lng+1);
            if (!q) return -2;
     
            memset(p, 0, lng+1);
            memset(q, 0, lng+1);
            memcpy(q, strin, lng);
     
            for (i = 0; i < lng; i++) {
                 j = (255 - (i & 254)) | (127 ^ i);
                 p[i] = q[i] ^ (char)j;             
             }
             memset(strout, 0, sizeof(lng+1));
             memcpy(strout, p, lng);
             free(p);
             free(q);       
             return 0;
      }
      else return -3;
    }
    Pour infos, les deux codes fonctionnent parfaitement.
    Cordialement.

  11. #11
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 071
    Points : 9 515
    Points
    9 515
    Par défaut

    Je ne comprends plus où est ton problème .

    1 - Tu nous parles de structure : on ne voit pas de structure dans ton code.

    2 - On ne voit pas ton code côté pascal.

    Il faudrait avoir l'ensemble de tes codes pour pouvoir t'aider.

    Ami calmant, J.P

  12. #12
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut
    Bonjour,
    La struct en C passe dans la fonction en tant que (char *) :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct TsCodeAccess {
            char Code[16];
            long DateD;
            long DateF;
            char ip[20];
            int  illimited;
    };
    En Pascal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    TYPE
      TsCodeAccess = Record
              Code : String[16];
              DateD: longint;
              DateF: longint;
              ip:String[20];
              illimited:integer;
    end;
    Le cast entre PChar et pointeur de cette structure est très compliqué. J'utilise PChar pour le passage des arguments à la DLL.
    Je procède d'abord à charger le fichier contenant un enregistrement crypté, je charge la DLL et j'appelle la 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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    //****************************************************************************
    function  cryptage(var strin:PChar; var strout:PChar; lng:integer):integer; cdecl; external 'MyDll.dll';
     
    procedure TForm1.ChargerFichierClick(Sender: TObject);
    TYPE
      TEncrypter = function (var strin:PChar; var strout:PChar; lng:Integer):integer; cdecl;
    VAR
        OpenDialog1 : TOpenDialog;
        fp               : Handle;
        i, rc, lng       : integer;
        HandleDLL    : TLibHandle;
        Encrypter     : TEncrypter;
        pstri, pstro   : PChar;
    //    scd           : TsCodeAccess;
    //    pscd         : ^TsCodeAccess;
    //    Tin, Tout    : Array[0..Sizeof(TsCodeAccess)] Of Char;
     
    begin
      G_File := 'D:\tmp\BT.bin';
      lng := Sizeof(TsCodeAccess);
      pstri := StrAlloc(lng + 1);
      pstro := StrAlloc(lng + 1);
      pstri := '';
      pstro := '';
      If FileExists(G_File) Then
         begin
            fp := FileOpen(G_File, fmOpenRead);
            rc := FileRead(fp, pstri^, lng);    // pstri récupère la chaîne cryptée (lecture dans le fichier)
            FileClose(fp);
            if fileexists(PathLib) Then
               begin
                 HandleDLL := 0;
                 HandleDLL := LoadLibrary(pAnsiChar(PathLib));
                 if (HandleDLL <> 0) then
                  begin
                    // Chargement de la procédure
                    Encrypter :=  TEncrypter(GetProcedureAddress(HandleDLL,'cryptage'));
                    if Assigned(Encrypter) then
                      begin
                        rc := Encrypter(pstri, pstro, lng);   // Exécution de la procédure cryptage de la DLL
    // pstri  = la chaîne à décrypter lue à partir du fichier 
    // pstro = le résultat du décryptage
    // =====> avant l'appel à Encrypter, la valeur de pstri est correcte
    // =====> en sortant de la fonction la pstri est perdue et la valeur de pstro n'est pas cohérente
                      end
                    else
                      begin
                        ShowMessage('Procédure <dfci_cryptage> introuvable');
                      end;
                    FreeLibrary(HandleDLL);
                  end
                  else
                    begin
                      ShowMessage('Erreur DLL impossible à charger');
                      Close;
                    end;
               end;
         end;
      StrDispose(pstri);
      StrDispose(pstro);
    end;
    Par ailleurs, j'utilise la même DLL avec Dev-c++ ou avec Builder C++, tout fonctionne correctement.
    Si vous me poser la question : pourquoi je développe avec Lazarus ?
    Cet outil de développement RAD est puissant et gratuit, je n'ai pas trouvé l'équivalent en C/C++.
    Pour remédier le problème rapidement avec Lazarus, je n'utilise pas mes DLL, je convertis en Pascal mes outils en C, puis je les intègre dans mes applications.
    Ce n'est pas une solution mais c'est un dépannage ponctuel.
    Je vous remercie de votre soutien
    Bien cordialement.

  13. #13
    Membre éprouvé
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    432
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 432
    Points : 1 128
    Points
    1 128
    Par défaut
    Bonjour,

    ne se traduit pas par
    mais par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    code : array[0..15] of char;
    En effet le premier caractère de ta chaîne pascal String[16] en contient la longueur et est suivi de 16 caractères. Tu as donc 17 caractères.
    De plus il faudrait voir si il ne faut pas compacter ta structure (directive packed).

    Cordialement

  14. #14
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2008
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2008
    Messages : 73
    Points : 70
    Points
    70
    Par défaut
    Bonjour,
    Merci pour la correction, j'ai complètement oublié de déclarer les champs en tant que 'Array'.
    Bien sûr, une chaîne de type String ne correspond pas à un tableau de caractères.
    Par ailleurs, il y a un problème avec l'appel de la fonction DLL :

    1- D'abord je récupère l'enregistrement codé à partir du fichier (la valeur est correcte) dans la variable str_input, que je passe en 1er argument à la fonction de décryptage, mais en quittant l'appel de la fonction : Encrypter(str_input, str_output, lng), str_input perd sa valeur : str_input <Address 0x..... out of bounds>.
    J'ai refait le test avec Dev-c++ et la même DLL :
    - j'ai récupéré l'enregistrement codé
    - je l'ai décodé avec la fonction Encrypter, la valeur retournée est correcte.
    - la même valeur retournée est à nouveau codée et enregistrée dans un autre fichier
    - ce dernier fichier est lu, l'enregistrement décodé est juste.
    Donc je n'ai pas de soucis avec le code source en C, ni avec l'appel de la fonction DLL.

    ce n'est pas grave, je ne vois pas le problème rencontré en Pascal, j'ai déjà intégré le décryptage dans l'application.
    Bien cordialement.

  15. #15
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 071
    Points : 9 515
    Points
    9 515
    Par défaut
    hello,
    Citation Envoyé par tonton67 Voir le message
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //****************************************************************************
    function  cryptage(var strin:PChar; var strout:PChar; lng:integer):integer; cdecl; external 'MyDll.dll';
    Il me semble que le var est en trop car PChar est déjà un pointeur.

    Voici du code qui fonctionne chez moi entre un programme Lazarus et une dll en c fabriquée avec dev-c++
    La procédure appellée MonTest a 4 arguments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    type
       TMonTest = procedure(msgin: PAnsiChar;msgout: PAnsiChar;intIn: integer; var intOut: integer); cdecl;
    Le premier argument est une chaîne transmise.
    Le deuxième est une chaîne modifiée par la routine en C
    Le troisième est un entier
    Le quatrième est un entier transmis par référence pour pouvoir le modifier :
    Voici le code d'appel côté Lazarus :
    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
    procedure TForm1.Button3Click(Sender: TObject);
       var
       // Creates a suitable variable (data field) for the DLL subroutine
       MonTest : TMonTest;
       // Creates a handle for the DLL
       LibHandle: TLibHandle = NilHandle;
       FarProc: TFarProc;
       bufOut :  array [0..255] of Char;
       intIn : integer;
       intOut : integer;
       s: string;
       begin
       // Get the handle of the library to be used
       LibHandle := LoadLibrary('D:\temp\tstLibLaz.dll');
       // Checks whether loading the DLL was successful
       if LibHandle <> 0 then
         begin
           // Assigns the address of the subroutine call to the variable funStringBack
           // 'funStringBack' from the DLL DLLTest.dll
           FarProc := GetProcedureAddress(LibHandle, 'MonTest');
     
     
           // Checks whether a valid address has been returned
            if FarProc <> nil then
             begin
                MonTest := TMonTest(FarProc);
                MonTest(PChar('toto'),PChar(bufOut),200,intOut);
     
     
                ShowMessage('retour : ' + strPas(PChar(bufOut)) + ' - ' + inttostr(intout));
             end;
         end;
     
     
       // release library
       UnloadLibrary(LibHandle);
     
     
    end;
    A noter que bufOut doit avoir une taille supérieure à la taille max de la chaîne qui sera renvoyée.
    Voici le code côté c :
    dll.h :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef _DLL_H_#define _DLL_H_
     
     
    #if BUILDING_DLL
    #define DLLIMPORT __declspec(dllexport) __cdecl
    #else
    #define DLLIMPORT __declspec(dllimport) __cdecl
    #endif
    DLLIMPORT void MonTest(char* MsgIn,char* MsgOut,int IntIn, int* IntOut);
    #endif

    dllmain.c :
    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
     
    #include "dll.h"
    #include <windows.h>
    #include <string.h>
     
     
    DLLIMPORT void MonTest(char* MsgIn,char* MsgOut,int IntIn, int* IntOut)
    {
        MessageBox(0,MsgIn,"Hi",MB_ICONINFORMATION);
        strcpy(MsgOut, "coucou");
        MessageBox(0,MsgOut,"Hi",MB_ICONINFORMATION);
        *IntOut = IntIn;
    }
     
     
    BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
    {
        switch(fdwReason)
        {
            case DLL_PROCESS_ATTACH:
            {
                break;
            }
            case DLL_PROCESS_DETACH:
            {
                break;
            }
            case DLL_THREAD_ATTACH:
            {
                break;
            }
            case DLL_THREAD_DETACH:
            {
                break;
            }
        }
     
        /* Return TRUE on success, FALSE on failure */
        return TRUE;
    }

    Ami calmant, J.P

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 02/09/2008, 16h17
  2. Utilisation d'une bib. (écrite en Java) dans un programme écrit en C++
    Par Farida1702 dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 13/04/2007, 13h51
  3. Réponses: 8
    Dernier message: 07/12/2005, 11h18
  4. Réponses: 6
    Dernier message: 21/06/2005, 21h45
  5. Utilisation d'une dll écrite en delphi 5 dans VB6
    Par Jean-Louis dans le forum Langage
    Réponses: 4
    Dernier message: 05/08/2002, 09h19

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