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

MFC Discussion :

[MFC] - Creation de librairie statique contenant du code MFC


Sujet :

MFC

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Nicolas Bauland
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 119
    Par défaut [MFC] - Creation de librairie statique contenant du code MFC
    Bonjour,

    Je développe une application MFC. Pour un besoin d'installation pratique, il est impératif que cette application soit liée statiquement aux mfc.
    Lors du développement, il est prévu de pouvoir réutiliser le code de certaines fonctions qui devront donc être placées dans une librairie statique. Ces fonctions utilisent parfois des classes MFC.

    J'ai l'impression de me mélanger les pinceaux lors de ce développement:
    • J'arrive à paramétrer l'appli pour être liées statiquement aux MFC
    • J'arrive à créer ma librairie statique, que je rempli de fonctions,
    • Je place bien le .h de la librairie dans le code source de l'appli,
    • J'ajoute le lien à .lib dans le code source de l'appli(j'ai essaye par un #pragma ou directement dans les options du projet),
    • J'ai un message m'indiquant qu'il ne trouve pas la fonction (voir ci dessous).


    Est-ce bien la bonne procedure ? Sinon, qu'ai-je loupé ?

    Message:
    Erreur 1 error LNK2019: symbole externe non résolu "void __cdecl BNetwork::WakeUp(class ATL::CStringT<wchar_t,class StrTraitMFC<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >)" (?WakeUp@BNetwork@@YAXV?$CStringT@_WV?$StrTraitMFC@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@@Z) référencé dans la fonction "public: void __thiscall CTestXLSDBDlg::OnPosteAllumer(void)" (?OnPosteAllumer@CTestXLSDBDlg@@QAEXXZ) D:\Programmation\Projets\ELGestion\trunk\TestXLSDB\TestXLSDBDlg.obj

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 487
    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 487
    Par défaut
    Combien de fois il faut que je dise qu'exporter des classes C++, C'EST MAL.

    Votre problème n'a rien à voir avec les MFC.

    Le linker cherche, et ne trouve pas, la méthode avec la signature "void __cdecl BNetwork::WakeUp(class ATL::CStringT<wchar_t,class StrTraitMFC<wchar_t,class ATL::ChTraitsCRT<wchar_t> > >)".

    - "__cdecl", si, lors de la compilation de la lib, la convention d'appel par défaut n'est pas "__cdecl", vous avez perdu.
    A moins, bien sûr que vous avez explicitement déclaré les conventions d'appel de chacune de vos méthodes et fonctions. Mais j'en doute.

    - "class ATL::CStringT", si, lors de la compilation de la lib, la classe Cstring n'est pas transformé en ATL::CStringT, vous avez perdu.
    Il faut regarder du côté des options de compilation de la lib.

    - "wchar_t", si, lors de la compilation de la lib, la constante de compilation "UNICODE" ou équivalent n'est pas définie, vous avez perdu.

    - "StrTraitMFC", si, lors de la compilation de la lib, StrTraitMFC n'est pas "le trait" par défaut de la classe template ATL::CStringT, vous avez perdu.

    ...

    Exporter des classes C++, C'EST MAL, C'EST MAL, C'EST MAL. Et ce n'est pas une règle à l'emporte pièce. Et votre problème en est l'illustration.

    P.S.: vous avez perdu.

  3. #3
    Membre expérimenté
    Avatar de Nicolas Bauland
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 119
    Par défaut
    Soit c'est mal, voir très mal.

    Maintenant que faire ? Comment exporter ces fonctions qui font références à des classes ?
    J'ose espérer qu'il existe au moins une solution.

    Si je ne dois pas exporter de classe, que puis-je faire pour exporter ce genre de fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int Func(CString str, int nb);

  4. #4
    Membre éprouvé
    Avatar de TheGzD
    Homme Profil pro
    Ingénieur/ Docteur en Informatique
    Inscrit en
    Avril 2007
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur/ Docteur en Informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 327
    Par défaut
    Ne pas se mettre en Multi-threaded Debud DLL peut aussi régler ce genre de désagréments il me semble.
    Essaye d'utiliser /MTd et non /MDd si c'est le cas.

    Courage.

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 487
    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 487
    Par défaut
    Vouloir exporter des classes, c'est obliger les utilisateurs de cette librairie à un compilateur, voir à une version du compilateur, correspondant à celui qui à généré le dll.
    Cela oblige aussi les utilisateurs de cette librairie à utiliser des options de compilations compatibles entre la compilation de la librairie et celle du code utilisateur.
    Vous devrez donc spécifier le compilateur nécessaire à l'utilisation de votre librairie, voir fournir plusieurs versions de votre librairie en fonction du compilateur, de sa version et des options de compilation à supporter. Bon courage.
    Le .h de votre librairie devra aussi détecter les options de compilations lors de son inclusion et générer une erreur de compilation quand il détectera des options et constantes de compilations incompatibles. Il faut faire au moins un minimum, comme la vérification du type de C-Runtime, la remarque de TheGzD en est l'illustration. Cette vérification doit être faites automatiquement à la compilation, avec l'inclusion du .h dans un projet.

    Si je ne dois pas exporter de classe, que puis-je faire pour exporter ce genre de fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int Func(CString str, int nb);
    Pas mal le passage d'une string en paramètre avec recopie.
    Pensez aux références const.

    Ce n’est pas le plus compliqué comme fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WINAPI int Func([in]LPCSTR str, [in]int nb);
    Le [in], c'est pour la déco, mais c'est toujours utile de savoir le sens de passage des paramètres. Dans la même veine, spécifiez ce qui est modifiable, d'où le C de LPCSTR.

    Rien ne vous empêche de spécifier des classes dans les .h de votre librairie qui encapsuleront vos fonctions dans des méthodes de classe. Mais les instances de ces classes seront générées dans du code compilé lors de l'utilisation de la librairie, pas au moment de la compilation de la librairie, donc avec des options compatibles avec le code utilisateur. Ces classes ne seront que des wrappers sans intelligence mais pouvant faciliter l’utilisation de la librairie. Elles n’ont pas à être les mêmes que celles utilisées dans le code de la librairie elle-même.

    Il faudra donc que vous identifiez toutes les options et constantes de compilations qui influenceront le mangling de vos méthodes et que vous ajoutiez le code de vérification de ces options et constantes dans le .h de votre librairie.
    Une fois cette tâche ingrate faites, il ne vous restera qu’à inclure votre .h dans le projet utilisateur. Lors de la compilation du projet utilisateur, les informations que vous avez distillées dans les messages d'erreur du code de vérification dans le .h devraient vous indiquer les options à ajouter ou à supprimer du projet utilisateur pour qu'ils soient compatibles avec la librairie.

    En un mot vous devez contrôler options de compilations du code utilisateur dans le .h de la librairie, mais il faut absolument que vous maîtrisiez un minimum les pré-requis nécessaires à l'utilisation de votre lib C++.
    qu'exporter des classes C++, C'EST MAL.
    Bis, ter ...

  6. #6
    Membre émérite
    Avatar de Gabrielly
    Inscrit en
    Juin 2004
    Messages
    722
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 722
    Par défaut
    Combien de fois il faut que je dise qu'exporter des classes C++, C'EST MAL.
    C'est quelle compagne ça!!!!

    Qui a dit qu'exporter des classes C++ c'est mal?

    A quoi servent les DLLs d'extension MFC?

    Si vous travaillez avec MFC pourquoi se compliquez avec les versions de compilo utiliser votre Visual Studio.

    On peut avoir des solutions de projets qui sont essentiellement des dlls d'extension MFC contenant des classes de bases réutilisables pour une application MFC (exe)

    Par exemple on peut avoir une solution de 4 projets:

    dans une dll d'extension MyBase.dll on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class AFX_EXT_CLASS CMyBaseWinApp : public CWinAppEx { ... };
    class AFX_EXT_CLASS CMyBaseMainFrame : public CMDIFrameWndEx { ... };
    class AFX_EXT_CLASS CMyBaseDocument : public CDocument { ... };
    class AFX_EXT_CLASS CMyBaseTreeView : public CTreeView { ... };
    class AFX_EXT_CLASS CMyBaseDockablePane : public CDockablePane { ... };
    class AFX_EXT_CLASS CMyPersonnalMfcClass : public CObject { ... };
    dans une autre dll d'extension MyExtend.dll on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class AFX_EXT_CLASS CMyRichWinApp : public CMyBaseWinApp { ... };
    class AFX_EXT_CLASS CMyRichMainFrame : public CMyBaseMainFrame { ... };
    class AFX_EXT_CLASS CMyRichDocument : public CMyBaseDocument { ... };
    class AFX_EXT_CLASS CMyRichTreeView : public CMyBaseTreeView { ... };
    class AFX_EXT_CLASS CMyRichDockablePane : public CMyBaseDockablePane { ... };
    class AFX_EXT_CLASS CMyRichPersonnalMfcClass : public CMyPersonnalMfcClass { ... };
    dans une application MFC MySimpleApp.exe on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class AFX_EXT_CLASS CSimpleWinApp : public CMyBaseWinApp { ... };
    class AFX_EXT_CLASS CSimpleMainFrame : public CMyBaseMainFrame { ... };
    class AFX_EXT_CLASS CSimpleDocument : public CMyBaseDocument { ... };
    class AFX_EXT_CLASS CSimpleTreeView : public CMyBaseTreeView { ... };
    class AFX_EXT_CLASS CSimpleDockablePane : public CMyBaseDockablePane { ... };
    class AFX_EXT_CLASS CSimplePersonnalMfcClass : public CMyPersonnalMfcClass { ... };
    dans une autre application MFC MyPowerApp.exe on a:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class AFX_EXT_CLASS CPowerWinApp : public CMyRichWinApp { ... };
    class AFX_EXT_CLASS CPowerMainFrame : public CMyRichMainFrame { ... };
    class AFX_EXT_CLASS CPowerDocument : public CMyRichDocument { ... };
    class AFX_EXT_CLASS CPowerTreeView : public CMyRichTreeView { ... };
    class AFX_EXT_CLASS CPowerDockablePane : public CMyRichDockablePane { ... };
    class AFX_EXT_CLASS CPowerPersonnalMfcClass : public CMyPersonnalMfcClass { ... };
    Voici les principes d'utilisation efficaces des dlls sans se perdre avec les *.h ou les lib ou les problèmes de référencement entre projets. D'ailleurs je pouvais même ajouter des dll .NET comme des projets dans la même solution et qui soit exploitable par ces 4 projets natives mais qui deviendraient mixte dans ce cas. Mais restons en là d'abord au monde du natif.

    1. Project Dependencies
    Il faut régler le problème de dépendances des projets dans la configuration de votre solution. MyBase.dll vient en premier, MyExtend.dll vient en second ensuite les exe MySimpleApp.exe en troisième et MyPowerApp.exe en quatrième. Ainsi lors de la compilation de la solution (je n'ai pas dis du projet) les projets qui la composent sont compilés dans le bon ordre.

    2. Les includes
    Puisque les dlls sont aux services des exe. Il est préférable de ranger la définition de chacune de vos classes exportables dans des fichiers séparés.

    Par exemple dans MyBase.dll on a :
    CMyBaseWinApp dans son MyBaseWinApp.h
    CMyBaseMainFrame dans son MyBaseMainFrame.h
    CMyBaseDocument dans son MyBaseDocument.h
    etc...

    Et ensuite réunir l'ensemble de ces includes dans un seul fichier MyBase.h comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // MyBase.h
    #pragma once
    #include "MyBaseWinApp.h"
    #include "MyBaseMainFrame.h"
    #include "MyBaseDocument.h"
    etc
    Idem pour la dll MyExtend.dll

    Au final pour ce qui est des includes nous n'avons que 2 fichiers MyBase.h et MyExtend.h

    3. Paramétrages des output des projets
    Ici il est maintenant question de paramétrer les sorties des projets de votre solution.
    Vous devez vérifier ou configurer vos projets de manière à ce que leurs output soient produits aux mêmes endroits. Afin d'éviter à un projet de réclamer un output dont il dépend (par exemple une librairie qu'il ne voit pas)
    Dans les options de chaque projet il faut définit un output directory commun généralement General > Output Directory : votre répertoire (debug)
    Toujours dans les options Linker > Advanced > Import Library : le path de vos lib

    4. Référencer les includes
    Puisque MyExtend.dll dépend de MyBase.dll il faut inclure son unique fichier MyBase.h dans le stdAfx.h du projet MyExtend.dll
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // stdAfx.h de MyExtend.dll
    ...
    #include "..\Mybase\MyBase.h"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // stdAfx.h de MySimpleApp.exe
    ...
    #include "..\Mybase\MyBase.h"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // stdAfx.h de MyPowerApp.exe
    ...
    #include "..\Mybase\MyBase.h"
    #include "..\MyExtend\MyExtend.h"
    En effet le stdAfx.h est le meilleur endroit.

    5. Référencer les librairies
    Nous savons que les 4 projets sont dépendants dans l'ordre suivant
    MyBase.dll > MyExtend.dll > MySimpleApp.exe > MyPowerApp.exe

    pour MyExtend.dll
    Linker > Input > Additional Dependencies : MyBase.lib

    pour MySimpleApp.exe
    Linker > Input > Additional Dependencies : MyBase.lib;

    pour MyPowerApp.exe
    Linker > Input > Additional Dependencies : MyBase.lib;MyExtend.lib


    Bon je crois que je n'ai rien oublié. Compilez la solution, définissez le projet le projet de démarrage et lancer l'exécution de votre Power MFC Application!!!

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 23/03/2013, 08h15
  2. Création d'une librairi c++ contenant du code c avec code bloc
    Par lyhleandrho dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 29/02/2012, 13h02
  3. Creation d'une librairie statique
    Par Kaldwin dans le forum Débuter
    Réponses: 0
    Dernier message: 14/12/2010, 00h10
  4. Création et utilisation de librairies statiques avec Code::Blocks
    Par somberlord dans le forum Code::Blocks
    Réponses: 1
    Dernier message: 22/07/2007, 08h58
  5. Réponses: 2
    Dernier message: 19/08/2005, 16h02

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