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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    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
    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 : 694
Taille : 9,4 Ko

    Merci pour un conseil de débogage.
    Cordialement

  2. #2
    Membre Expert
    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
    Billets dans le blog
    2
    Par défaut
    Bonjour, il faut que tu compiles ta bibliotheque C++ en un fichier DLL compatible avec Windows.
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  3. #3
    Membre confirmé
    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
    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
    Membre Expert
    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
    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
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  5. #5
    Membre confirmé
    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
    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 934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 934
    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.
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

+ 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