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++Builder Discussion :

Utilisation d'une DLL visualstudio avec CBuilder Xe5 [Système/Fichiers/API]


Sujet :

C++Builder

  1. #1
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 084
    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 084
    Points : 1 525
    Points
    1 525
    Billets dans le blog
    5
    Par défaut Utilisation d'une DLL visualstudio avec CBuilder Xe5
    Salut à tous

    Voilà ce petit post qui n'est pas une question mais plutôt une solution à un problème que j'ai eu et que j'ai pu résoudre en naviguant dans pas mal de post à droite et à gauche.
    Si jamais il n' a pas ça place ici .Toutes mes excuses aux modérateurs et administrateurs

    Voici le problème:
    J'ai écris une DLL en C/C++ avec visual studio 2013 et je veux l'utiliser avec CBuilder Xe5.
    Voici un extrait du .h et du .cpp de ma DLL (il s'agit de fonction très simple pour vérifier que ça marche).

    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
     
    // Le bloc ifdef suivant est la façon standard de créer des macros qui facilitent l'exportation 
    // à partir d'une DLL. Tous les fichiers contenus dans cette DLL sont compilés avec le symbole MADLL2_EXPORTS
    // défini sur la ligne de commande. Ce symbole ne doit pas être défini dans les projets
    // qui utilisent cette DLL. De cette manière, les autres projets dont les fichiers sources comprennent ce fichier considèrent les fonctions 
    // MADLL2_API comme étant importées à partir d'une DLL, tandis que cette DLL considère les symboles
    // définis avec cette macro comme étant exportés.
    #ifdef MADLL2_EXPORTS
    #define MADLL2_API __declspec(dllexport)
    #else
    #define MADLL2_API __declspec(dllimport)
    #endif
    	extern MADLL2_API int nMaDLL2;
     
    	MADLL2_API int fnMaDLL2(void);
    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
     
    // MaDLL2.cpp*: définit le point d'entrée pour l'application DLL.
    //
     
    #include "stdafx.h"
    #include "MaDLL2.h"
     
     
    #ifdef _MANAGED
    #pragma managed(push, off)
    #endif
     
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
        return TRUE;
    }
     
    #ifdef _MANAGED
    #pragma managed(pop)
    #endif
     
    // Il s'agit d'un exemple de variable exportée
    MADLL2_API int nMaDLL2=0;
     
    // Il s'agit d'un exemple de fonction exportée.
    MADLL2_API int fnMaDLL2(void)
    {
    	return 42;
    }
    Après compilation sous visual studio je récupère 2 fichiers MaDll2.lib et MaDll2.dll
    Utilisé tel quel ça ne fonctionne pas j'ai des erreurs au niveau de l'édition de lien. Le fichier MaDll2.lib n'est pas lu par CBuilder. Il faut en construire un nouveau à partir du fichier MaDll2.dll avec l'utilitaire Implib.

    Dans une fenêtre console entrez la commande suivante:

    ImpLib -a MaDll2.lib et MaDll2.dll

    De plus j'ai modifié le .h de la manière suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifdef MADLL2_EXPORTS
    #define MADLL2_API __declspec(dllexport)
    #else
    #define MADLL2_API __declspec(dllimport)
    #endif
    extern "C" {
    	extern MADLL2_API int nMaDLL2;
    
    	MADLL2_API int fnMaDLL2(void);
    }
    Et ça fonctionne. En espérant que ce petit post soit utile à certains

  2. #2
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut
    bien vu
    il y a plusieurs post traitant ce sujet sur les forums Américains en autre
    La grande différence entre MS et Borland c'est dans la stucuture du fichier lib et obj
    COFF et OMF
    il reste toujours la possibilité plus simple à mon goût de charger la librairie dynamiquement
    et de la décharger lorsque l'on en a plus besoin

    Un tuto qui pourrait t'interesser http://lfe.developpez.com/DLL/
    cdlt

  3. #3
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 084
    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 084
    Points : 1 525
    Points
    1 525
    Billets dans le blog
    5
    Par défaut
    Merci pour le lien. Je pense que je vais m'en servir sous peu

  4. #4
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 084
    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 084
    Points : 1 525
    Points
    1 525
    Billets dans le blog
    5
    Par défaut Quand ça a marché ça marche plus
    Bonjour

    Je relance ce post car ayant changé de version de visual studio (je suis en 2017) et de CBuilder (Je suis en RAD Studio 10 Seattle)
    Plus rien ne fonctionne
    Donc le .h de ma DLL
    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
     
    #pragma once
    #ifdef _WINDLL 
    #define DLLDEC __declspec(dllexport) 
    #else 
    #define DLLDEC __declspec(dllimport) 
    #endif 
    #ifdef __cplusplus 
    extern "C"
    {
    #endif 
    	DLLDEC int Test();
    	DLLDEC int fft(double *valreelIn, double *valimagIn, double *valreelOut, double *valimagOut, int nbval);
    #ifdef __cplusplus 
    }
    #endif
    Mon code C dans RAD STudio
    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
     
    // ---------------------------------------------------------------------------
     
    #include <fmx.h>
    #pragma hdrstop
     
    #include "TestDLLMain.h"
    #include "fastFFT.h"
    // ---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.fmx"
    TForm1 *Form1;
     
    // ---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
    }
     
    // ---------------------------------------------------------------------------
    void __fastcall TForm1::btnCalculClick(TObject *Sender) {
    	int ok=Test();
     
    }
    // ---------------------------------------------------------------------------
    Et voici l'erreur retournée:
    [ilink64 Erreur] Error: Unresolved external 'Test' referenced from D:\PROJETS\C++\TESTCBUILDER\INTEGREDLL\WIN64\DEBUG\TESTDLLMAIN.O

    Manifestement il n'arrive pas à trouver la fonction Test qui est dans ma DLL mais je n'arrive pas à comprendre pourquoi.
    J'ai construit un .lib à partir de ma DLL avec ImpLib et j'ai ajouté ce .lib à mon projet

    Une idée???

  5. #5
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut,
    Si ta DLL est en 64 Bits, malheureusement pour toi les outils implib sont incompatibles
    Embarcadero a semble-il oublié de développer une version 64 bits de cet outil

    cordialement

  6. #6
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut
    J’ai peut-être parlé un peu vite concernant Embarcadero lis l’article suivanthttp://docwiki.embarcadero.com/RADSt...s_pour_C%2B%2B
    Cordialement

  7. #7
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 084
    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 084
    Points : 1 525
    Points
    1 525
    Billets dans le blog
    5
    Par défaut
    J'ai essayé MKEXP qui m'a bien généré un .a que j'ai inclus dans mon projet CBuilder mais j'ai hélas la même erreur
    J'ai réessayé en 32 bits avec ImpLib mais ça ne fonctionne pas plus

  8. #8
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut
    Une autre possibilité
    utilise les outils 64 bits de MS par exemple Depends qui est livré avec la distribution Visual studio
    Note les fonctions exportés telles qu'elle apparaissent dans le tools en question

    Dans C++ Builder fait une importation dynamique de ta DLL avec LoadLibrary
    utilise GetProcAdrress pour obtenir l’adresse des fonctions exportées de ta DLL

    cdlt

  9. #9
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut,
    j'ai repris mon clavier pour faire un petit essai de DLL64 Bits générées depuis Visual Studio 2017

    le code est le suivant:
    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
     
    #define DLLDEC _declspec(dllexport)
     
    extern "C"
    {
    	DLLDEC int Test(int *value);
    	DLLDEC int fft(double *valreelIn, double *valimagIn, double *valreelOut, double *valimagOut, int nbval);
    }
     
     
     
    DLLDEC int Test(int * value)
    {
    	return DLLDEC(*value + 2);
    }
     
    DLLDEC int fft(double * valreelIn, double * valimagIn, double * valreelOut, double * valimagOut, int nbval)
    {
    	return DLLDEC int();
    }
    Après génération réussie de la dll je génére le fichier d'importation avec l'outil Embarcadero Mkexp. exe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    mkexp MyDll.a Mydll.dll
    je vais utiliser ma fonction exportée Test qui utilise un paramètre passé par adresse et retourne le continu du paramètre additionné de 2

    le code de mon app de test C++ Builder en 64 Bits

    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
     
    //---------------------------------------------------------------------------
     
    #ifndef Unit97H
    #define Unit97H
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
    #include <Vcl.Forms.hpp>
    #include <Vcl.ComCtrls.hpp>
    #include <Vcl.ToolWin.hpp>
    //---------------------------------------------------------------------------
    class TForm97 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TStatusBar *StatusBar1;
    	TToolBar *ToolBar1;
    	TButton *Button1;
    	TEdit *Edit1;
    	void __fastcall Button1Click(TObject *Sender);
    private:	// Déclarations utilisateur
    public:		// Déclarations utilisateur
    	__fastcall TForm97(TComponent* Owner);
    	int Value;
    };
     
     
    #define DLLDEC _declspec(dllimport)
      extern "C"
      {
    	DLLDEC int Test(int *value);
    	DLLDEC int fft(double *valreelIn, double *valimagIn, double *valreelOut, double *valimagOut, int nbval);
       }
    //---------------------------------------------------------------------------
    extern PACKAGE TForm97 *Form97;
    //---------------------------------------------------------------------------
    #endif
    le cpp
    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
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "Unit97.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm97 *Form97;
    //---------------------------------------------------------------------------
    __fastcall TForm97::TForm97(TComponent* Owner)
    	: TForm(Owner)
    {
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm97::Button1Click(TObject *Sender)
    {
      Value=4;
     Edit1->Text= IntToStr(Test(&Value));// Additionne 2 à Value
    }
    //---------------------------------------------------------------------------
    le résultat après appui sur le bouton

    Nom : Capture.PNG
Affichages : 161
Taille : 4,8 Ko

    le résultat est conforme

    conclusion c'est du côté du code de ta dll qu'il faut chercher le problème

    bon courage

    cordialement

  10. #10
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 084
    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 084
    Points : 1 525
    Points
    1 525
    Billets dans le blog
    5
    Par défaut
    Finalement j'ai trouvé une solution en utilisant

    LoadLibrary et GetProcAddress

    Dans visual studio
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #pragma once
    #if defined(LIBRARY_EXPORT) // inside DLL
    #   define App_API   __declspec(dllexport)
    #elif defined(LIBRARY_IMPORT) // outside DLL
    #   define App_API   __declspec(dllimport)
    #endif
     
    extern "C" App_API int ajoute(int a, int b);
    je définie LIBRARY_EXPORT dans visual studio et par contre je défini LIBRARY_IMPORT dans C++Builder

    Dans C++Builder au moment de la création de ma fenêtre je charge ma dll et je récupères les adresses des fonctions
    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
    //---------------------------------------------------------------------------
    
    #ifndef TestDLL3H
    #define TestDLL3H
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
    #include <Vcl.Forms.hpp>
    //---------------------------------------------------------------------------
    typedef int (__cdecl *AJOUTE)(int,int);
    //---------------------------------------------------------------------------
    class TForm2 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TButton *Button1;
    	void __fastcall Button1Click(TObject *Sender);
    	void __fastcall FormCreate(TObject *Sender);
    private:	// Déclarations utilisateur
    
    HMODULE _dll;
    AJOUTE f_ajoute;
    
    public:		// Déclarations utilisateur
    	__fastcall TForm2(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm2 *Form2;
    //---------------------------------------------------------------------------
    #endif
    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
     
    // ---------------------------------------------------------------------------
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "TestDLL3.h"
    #include "dllsimple.h"
    // ---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm2 *Form2;
     
    // ---------------------------------------------------------------------------
    __fastcall TForm2::TForm2(TComponent* Owner) : TForm(Owner) {
    }
     
    // ---------------------------------------------------------------------------
     
    void __fastcall TForm2::Button1Click(TObject *Sender) {
    	int n = f_ajoute(4, 22);
    	Button1->Caption = n;
    }
    // ---------------------------------------------------------------------------
     
    void __fastcall TForm2::FormCreate(TObject *Sender) {
    	_dll = LoadLibrary(L"dllsimple.dll");
    	if (_dll != NULL) {
    		f_ajoute = (AJOUTE)GetProcAddress(_dll, "ajoute");
    		int n = f_ajoute(2, 7);
    	}
    }
    // ---------------------------------------------------------------------------
    Et ça fonctionne

    Citation Envoyé par DjmSoftware Voir le message
    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
     //---------------------------------------------------------------------------
     
    #ifndef Unit97H
    #define Unit97H
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
    #include <Vcl.Forms.hpp>
    #include <Vcl.ComCtrls.hpp>
    #include <Vcl.ToolWin.hpp>
    //---------------------------------------------------------------------------
    class TForm97 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TStatusBar *StatusBar1;
    	TToolBar *ToolBar1;
    	TButton *Button1;
    	TEdit *Edit1;
    	void __fastcall Button1Click(TObject *Sender);
    private:	// Déclarations utilisateur
    public:		// Déclarations utilisateur
    	__fastcall TForm97(TComponent* Owner);
    	int Value;
    };
     
     
    #define DLLDEC _declspec(dllimport)
      extern "C"
      {
    	DLLDEC int Test(int *value);
    	DLLDEC int fft(double *valreelIn, double *valimagIn, double *valreelOut, double *valimagOut, int nbval);
       }
    //---------------------------------------------------------------------------
    extern PACKAGE TForm97 *Form97;
    //---------------------------------------------------------------------------
    #endif
    Je pense que le problème vient de ce que je n'avais pas mis la partie en rouge dans mon code

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 18/03/2015, 10h23
  2. Utilisation d'une DLL MFC avec Express
    Par CoRfr dans le forum MFC
    Réponses: 4
    Dernier message: 06/07/2011, 15h38
  3. Utiliser une DLL Delphi avec C#
    Par h8ciz dans le forum Windows Forms
    Réponses: 3
    Dernier message: 27/09/2007, 16h46
  4. [VC++] Utilisation d'une DLL écrite en C++ avec mingw.
    Par swirtel dans le forum Visual C++
    Réponses: 1
    Dernier message: 20/06/2007, 10h42
  5. [Wamp] Utilisation d'une dll VB avec php
    Par Tony_P dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 1
    Dernier message: 13/03/2007, 16h32

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