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

Visual C++ Discussion :

Comment créer (et ensuite utiliser) une bibliothèque statique sous Visual C++ express


Sujet :

Visual C++

  1. #1
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut Comment créer (et ensuite utiliser) une bibliothèque statique sous Visual C++ express
    Débutant en Visual C++, je souhaite recréer les bibliothèques xxx.lib que j'avais créées sous Borland C++. Je ne trouve pas de modèle dans la documentation en ligne. On me propose un modèle de "bibliothèques de classes", mais, comme je suis débutant, je ne comprends pas encore grand chose aux classes et je veux juste, pour l'instant, créer des fonctions C une fois pour toutes pour éviter d'avoir à en recopier le code dans tous mes programmes.

    Ensuite, j'imagine qu'il suffira d'inclure une référence au fichier .h (#include "xxx.h") et à la librairie (USELIB("c;\...\xxx.lib")) pour avoir accès à ces fonctions dans n'importe quel programme. Ai-je raison ? Où est-ce plus compliqué ?

    Merci d'avance pour tout conseil !

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Tu peux par exemple faire un projet Win32, et dans l'onglet général, tu mettras la propriété "Type de configuration" sur "Librairie statique (.LIB)".

    Après, je n'utilise pas VS Express mais la version complète, qui possède un wizard de création de librairie statique :
    • Panneau de gauche : Projet Visual C++, choix "Win32".
    • Panneau de droite : Projet Win32.
    • Valider le nom et le répertoire, cliquer sur "OK", puis "Next".
    • Cocher "Librairie statique" au lieu de "Application Windows", cliquer sur "OK".
    A voir s'il y a le même pour VS Express, ce qui devrait être le cas.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Merci de ta réponse !

    J'ai fait exactement ce que tu m'as dit. Le nom de mon projet est test13. Visual C++ a créé trois fichiers :
    stdafx.h, targetver.h, et stdafx.cpp

    Au pifomètre, j'ai choisi stdafx.cpp pour coder ma fonction "mafonction" (oui, c'est un test...). Puis, j'ai cliqué sur "générer->générer la solution" et ont été créés plusieurs fichiers dont un fichier test13.lib dans test13\debug. "test13.h" pour sa part n'a pas été créé, je suppose que c'est à moi de le faire, ce n'est pas un problème, bien sûr.

    A présent, si j'ai fait ce qu'il fallait faire, comment coder un programme appelant ? Je vais créer un programme qui dans son code va faire référence à mafonction(10) par exemple. Je devrais probablement inclure une ligne #include "c:\.....\test13.h" (que j'aurais créé préalablement), mais comment vais-je faire savoir au linker que la fonction manquante (mafonction) se trouve dans test13.lib ? Sous Borland C++, il fallait inclure une ligne USELIB("test13.lib") dans le code, et préciser au linker dans quel dossier se trouvaient les librairies auxquelles je faisait référence. Comment faire sous Visual C++ ? Apparemment, Visual C++ n'utilise pas ce mot "USELIB". La syntaxe est donc différente.

    Merci de me renseigner.

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Bon, quelques points importants :
    • VS crée quelques fichiers "de base", mais ils ont un rôle très particulier qu'il te faut connaître.
    • Targetver.hpp est un fichier destiné à paramétrer la version minimale de Windows requise par ton programme. Cela aura une importance si tu veux que ton programme tourne aussi bien sur Windows 2000 que Windows 7.
      Pour l'instant, laisse-le tel quel.
    • StdAfx.h est l'entête primaire pour les entêtes précompilés. Cela sert à accélérer la REcompilation de ton projet, ou la compilation utilisant BEAUCOUP de librairies. Sur un projet "simple", c'est parfois plus problématique qu'autre chose d'utiliser les entêtes précompilés.
      Pour l'instant, je te conseille de ne pas t'en servir, du moins tant que tu n'as pas bien compris le concept de compilation séparée et de modules.
    • StdAfx.cpp est le fichier permettant, justement, de construire les entêtes précompilés. Par défaut, il est vide, et il doit le rester. Ce n'est PAS un fichier pour y mettre ton code !
    • Un fichier .H n'est jamais compilé, ce ne sont QUE les fichiers .C ou .CPP qui le sont. Donc, c'est normal que ton fichier "test13.h" ne soit pas compilé, il ne le sera qu'au travers des fichiers C/CPP qui l'utilisent.
    • Donc : essaie plutôt de partir d'un projet vide pour démarrer, cela t'évitera quelques nœuds au cerveau pour rien. Tu as le temps d'apprendre les subtilités propres à Visual Studio un peu plus tard, concentres-toi sur le langage lui-même pour l'instant.


    Pour utiliser une librairie (statique ou dynamique) sous Visual, tu as deux solutions :
    • Référencer explicitement la librairie dans ton exécutable. On peut faire ça de deux façons :
      • L'ajouter dans le champ "Librairies additionnelles" de la partie "Edition de liens" des propriétés de ton projet.
      • Utiliser un "#pragma comment(lib,"MaLibrairie")" dans le code, qui correspond au USELIB de BC++ (voire cette discussion et cette FAQ).
    • Utiliser les dépendances au sein de la solution : bouton droit sur ton exécutable, "Dépendances", et coche la librairie à utiliser.
    • Dans les deux cas, il te faudra ajouter les chemins vers les includes de ta librairie dans ton projet de toutes façons (voir cette FAQ).


    Pour rejoindre l'autre discussion : avec les DLL, c'est pareil, car c'est un problème de compilation dans un premier temps. Pour les dépendances de projet, VS gère très bien le fait que ce soit une DLL ou une LIB : en effet, pour les DLL, il génère une librairie d'importation qui t'évite d'avoir à linker manuellement les fonctions de la DLL.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #5
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Achhhh ! Je ne comprends pas ! Désolé, j'ai la tête dure !
    Targetver.hpp est un fichier destiné ...Pour l'instant, laisse-le tel quel.
    Tu n'auras pas besoin de me dire ça deux fois ! Je n'y touche pas !
    StdAfx.h est l'entête primaire pour les entêtes précompilés...Pour l'instant, je te conseille de ne pas t'en servir
    Je n'y toucherai pas non pus !
    StdAfx.cpp est le fichier permettant, justement, de construire les entêtes précompilés. Par défaut, il est vide, et il doit le rester. Ce n'est PAS un fichier pour y mettre ton code !
    Bon, d'accord ! Mais, comme je te l'ai dit, c'est pourtant ce que j'ai fait ! J'ai cliqué sur "générer" et VS m'a effectivement créé un fichier test13.lib !!!!
    Qu'est-ce que peut bien contenir test13.lib à présent ???
    Un fichier .H n'est jamais compilé, ce ne sont QUE les fichiers .C ou .CPP qui le sont. Donc, c'est normal que ton fichier "test13.h" ne soit pas compilé, il ne le sera qu'au travers des fichiers C/CPP qui l'utilisent.
    Je n'ai pas dit que mon fichier test13.h n'était pas compilé ; j'ai dit qu'il n'existait pas. A fortiori ne peut-il pas être compilé ! Dans ma naïveté, j'ai pensé que VS allait me créer un fichier test13.cpp et me demander d'y loger mon code pour les fonctions que j'avais envie de mettre dans la LIB, et qu'il allait créer et remplir automatiquement un test13.h. J'ai justement remarqué qu'il n'avait rien fait de tel.
    Mon interprétation des fichiers .h est la suivante :
    Lorsqu'un code fait référence à une fonction qui n'existe pas dans ce code, le compilateur a besoin de connaître la syntaxe d'appel de la fonction pour indiquer à l'utilisateur si la fonction référencée est correctement appelée ou pas. Il laisse au linker le soin d'aller chercher où il pourra les fonctions précompilées dans des librairies (.lib) pour la création d'un exécutable complet, ou dans des librairies .dll lors de l'exécution. A mon avis, les fichiers .h ne sont pas compilés, car pas compilables ; elles ne contiennent que les prototypes des fonctions et pas leur code.
    Au demeurant, je trouve que cette expression "fichiers d'entête précompilés" est malheureuse. Le fichiers ne sont pas "précompilés" et ils ne seront pas davantage compilés ultérieurement. Ce sont les fonctions référencées dans ces fichiers qui ont été préalablement compilées, pas les fichiers, pas les entêtes ! Mais peut-être ai-je mal interprêté encore...
    Merci de me dire si j'ai au moins correctement compris ça !
    Donc : essaie plutôt de partir d'un projet vide pour démarrer
    Ça je ne comprends pas ! Je viens de demander à VS de créer une librairie qui s'appelle test13.lib ! Je m'attends par conséquent à trouver un fichier (genre test13.cpp) où je vais taper le code des fonctions que je vais mettre dans ma librairie. Je ne le trouve pas : VS ne l'a pas créé. Tu me dis de "partir d'un projet vide". Comment ? J'ai cliqué sur Nouveau->projet->CLR->Projet vide CLR ; j'ai donné le nom "bidon". A présent, la "solution" test13, contient deux "projets" : test13 et bidon ! L'explorateur Windows me dit que dans le dossier "test13", a été créé un sous-dossier bidon, qui contient un fichier bidon.vcproj et c'est tout. Par contre, dans la fenètre de VS est apparu, de manière légèrement différente un "projet" bidon avec trois petits rectangles jaunes (qui évoquent des sous-dossiers) intitulés "fichiers d'entete", fichiers ressources" et "fichiers sources". Mais toujours pas de test13.cpp ! Et cliquer sur ces trois petits rectangles n'a absolument aucun effet !
    Je ne sais toujours pas où je vais placer les trois lignes du code de ma fonction "mafonction" !!!

    Entre parenthèses, je n'ai pas compris ce qu'est une "solution", un "projet", pas plus que ce que signifie de cliquer sur "générer"

    Je te remercie beaucoup du temps que tu as passé à me répondre de manière extensive. Pour être moi-même conseilleur sur d'autres forums d'aide dans ma spécialité (qui n'est pas C++ - ce n'est pas un scoop !), je sais que cela prend beaucoup de temps. Je t'en suis par conséquent très reconnaissant. Je crains malheureusement que je n'aie pas encore fini de t'embêter avec mes questions...

    Merci mille fois !

  6. #6
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par ceugniet Voir le message
    Je n'ai pas dit que mon fichier test13.h n'était pas compilé ; j'ai dit qu'il n'existait pas.
    Oui, c'est à toi de les rajouter. Sur certains wizards VS, ces fichiers "vides" sont créés (notamment avec les DLL), mais pas toujours. De toutes façons, ce n'est qu'un cadre : rien ne t'empêche d'ajouter tous les fichiers (.H ou .CPP) que tu veux.

    Citation Envoyé par ceugniet Voir le message
    Au demeurant, je trouve que cette expression "fichiers d'entête précompilés" est malheureuse. Le fichiers ne sont pas "précompilés" et ils ne seront pas davantage compilés ultérieurement. Ce sont les fonctions référencées dans ces fichiers qui ont été préalablement compilées, pas les fichiers, pas les entêtes ! Mais peut-être ai-je mal interprêté encore...
    Et pourtant, si, ils sont bel et bien précompilés... C'est à dire que le compilateur va préprocesser et précompiler le maximum de données possible depuis un "point d'entrée" (StdAfx.h en général), c'est à dire le fichier racine de précompilation (ce point d'entrée) et TOUS les entêtes qu'il référence.
    Le temps gagné l'est principalement sur la phase de lecture des fichiers .H unitaires (on ne lit qu'un seul fichier, le .PCH [PreCompiled Headers]), de préprocess (c'est déjà fait), d'analyse lexicale / sémantique (c'est du binaire déjà "valide" et non plus du texte à vérifier), et sur les dépendances (elles sont incluses dans le PCH).

    Citation Envoyé par ceugniet Voir le message
    J'ai cliqué sur Nouveau->projet->CLR->Projet vide CLR ; j'ai donné le nom "bidon".
    Houlà, attention !!! Je t'ai dit de prendre un projet Win32, pas CLR !! CLR, c'est autre chose, c'est du C++ à la sauce .NET.

    Citation Envoyé par ceugniet Voir le message
    Je ne sais toujours pas où je vais placer les trois lignes du code de ma fonction "mafonction" !!!
    Dans des fichiers .H / .CPP que tu vas crééer, et ajouter (par drag & drop notamment) à ton projet. Ils vont se classer automatiquement dans les filtres de projet (les "pseudo-répertoires" que tu vois, comme "Fichiers d'entête").

    Citation Envoyé par ceugniet Voir le message
    Entre parenthèses, je n'ai pas compris ce qu'est une "solution", un "projet", pas plus que ce que signifie de cliquer sur "générer"
    Projet (extension .vcproj) : éléments permettant de compiler UN élément binaire. Un EXE, une DLL, une LIB, etc. Un projet ne peut pas (en situation normale) permettre de générer plus d'un objet de sortie "final" (EXE, DLL, LIB, ...). Donc, tu devras avoir un projet pour ton EXE, et un autre pour ta librairie.
    Solution (extension .sln) : Ensemble de projets reliés ensemble, notamment via les dépendances.
    Générer : compiler une solution ou un projet. Tu as une entrée de menu "Générer", justement.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  7. #7
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Merci de toutes ces informations complémentaires.

    J'ai enfin réussi à créer une librairie statique, et à l'utiliser dans un programme test ! Ca marche au poil !

    Mais, comme tu m'as convaincu qu'une DLL était bien mieux...j'ai essayé dans la foulée de faire de même pour une DLL. Et là, je ne sais pas quel pragma je dois insérer pour indiquer au linker que je vais utiliser cette dll là et pas une autre : il faut bien que je lui dise où chercher ses externes non résulus non ? Apparemment, le pragma comment (lib,...) ne fonctionne pas avec les dll ! Et je ne trouve pas :

    le champ "Librairies additionnelles" de la partie "Edition de liens" des propriétés de ton projet.
    En outre, tu dis que je peux cliquer sur l'exécutable et lui indiquer la dll qu'il faut utiliser, mais encore faudrait-il que l'exécutable existe, et justement, VS refuse de me créer mon exécutable qui teste la dll disant qu'il y a des externes non résolus !

    Merci encore !

  8. #8
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par ceugniet Voir le message
    Et là, je ne sais pas quel pragma je dois insérer pour indiquer au linker que je vais utiliser cette dll là et pas une autre : il faut bien que je lui dise où chercher ses externes non résulus non ? Apparemment, le pragma comment (lib,...) ne fonctionne pas avec les dll !
    Vérifie que tu génères bien une librairie d'importation (il doit y avoir un fichier .LIB de même nom généré à côté de la DLL), pour commencer.
    Ensuite, n'oublie pas que dans une DLL, tu dois impérativement déclarer ce qui est exporté de façon EXPLICITE. C'est le but des macros "NOMDELALIB_API" déclarée automatiquement par Visual lors de la création d'un projet DLL. Pour vérifier ça, utilise Dependancy Walker, et ouvre ta DLL. Dans le cadre au milieu, à droite, tu verras la liste des fonctions exportées par la DLL. Si c'est vide... Pas bon !

    Une fois que tu as une DLL qui exporte quelque chose, et que la librairie d'importation est générée, ça s'utilise comme une librairie statique (ou presque, mais ne t'en préoccupe pas pour l'instant). En tout cas, les #pragma fonctionneront.

    Citation Envoyé par ceugniet Voir le message
    En outre, tu dis que je peux cliquer sur l'exécutable et lui indiquer la dll qu'il faut utiliser, mais encore faudrait-il que l'exécutable existe, et justement, VS refuse de me créer mon exécutable qui teste la dll disant qu'il y a des externes non résolus !
    Vérifie les points ci-dessus, et une fois qu'ils seront réglés, ton exécutable linkera.
    On verra plus tard comment charger une DLL de façon réellement dynamique, pour l'instant, utilises-les de façon primaire le temps de démêler les pièges courants.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  9. #9
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Vérifie que tu génères bien une librairie d'importation (il doit y avoir un fichier .LIB de même nom généré à côté de la DLL), pour commencer.
    Ben non ! Il n'y a pas de fichier .LIB. Et je ne sais pas comment générer une "librairie d'importation" !!! (P.S. Bon, je viens de trouver : j'ai mis "oui" à la question "Bibliothèque d'importation ignorée" (Readme.txt : "...vous pouvez définir la propriété Ignore Input Library à la valeur Yes dans la page de propriétés Général du dossier éditeur de liens de la boîte de dialogue Pages de propriétés du projet..."), mais cela ne me génère toujours pas de calendll.lib !

    Citation Envoyé par Mac LAK Voir le message
    n'oublie pas que dans une DLL, tu dois impérativement déclarer ce qui est exporté de façon EXPLICITE. C'est le but des macros "NOMDELALIB_API" déclarée automatiquement par Visual lors de la création d'un projet DLL.
    Je risque pas de l'oublier : je ne l'ai jamais su ! Et je ne sais pas ce qu'est une macro, ni comment l'utiliser...
    (à la lumière de tes commentaires, j'ai finalement compris ce qui était écrit dans readme.txt ; j'ai bien compris que je dois "ajouter du code" dans le fichier mais comment ? )

    Je ne sais pas ce que c'est que "ce qui est exporté" ! S'agit-il des variables globales de la librairie ? Si oui, je me suis contenté, comme dans le cas de la LIB, de mentionner comme "extern" les variables globales mentionnées dans le .h. Quant aux macros "NOMDELALIB_API" ??? Je suppose qu'il s'agit d'un fichier calendll.api (ma librairie s'appelle calendll.dll) ? Mais point de calendll.api nulle part !!!
    Citation Envoyé par Mac LAK Voir le message
    Pour vérifier ça, utilise Dependancy Walker, et ouvre ta DLL.
    C'est quoi "Dependancy Walker" ??? Je suppose que c'est un utilitaire qui devrait faire partie de VS ! Mais je n'ai rien de tel, en tous cas je ne sais pas où le chercher !

    Citation Envoyé par Mac LAK Voir le message
    Une fois que tu as une DLL qui exporte quelque chose, et que la librairie d'importation est générée, ça s'utilise comme une librairie statique (ou presque, mais ne t'en préoccupe pas pour l'instant). En tout cas, les #pragma fonctionneront.
    Cela veut dire qu'il faut écrire :
    #pragma comment(lib,calendll.dll")
    ou bien
    #pragma comment(dll,calendll.dll")
    ?

    A moins que ce soit :
    #pragma comment(lib,calendll.lib")
    puisque VS devrait m'en créer une !!!


    Désolé pour ces centaines de questions ! Mais tout cela est entièrement nouveau pour moi ! Le moindre de tes mots me fait me gratter la tête :
    " librairie d'importation" ? C'est quoi ça ?
    "tu dois impérativement déclarer" ? Je veux bien déclarer mais comment ?
    "C'est le but des macros "NOMDELALIB_API" déclarée automatiquement" ? Ca consiste en quoi "déclarer" quand c'est VS qui déclare ? Il crée un fichier ? Du code ? Où ça ?

    Et merci de ta patience !

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par ceugniet Voir le message
    Ben non ! Il n'y a pas de fichier .LIB. Et je ne sais pas comment générer une "librairie d'importation" !!! (P.S. Bon, je viens de trouver : j'ai mis "oui" à la question "Bibliothèque d'importation ignorée" (Readme.txt : "...vous pouvez définir la propriété Ignore Input Library à la valeur Yes dans la page de propriétés Général du dossier éditeur de liens de la boîte de dialogue Pages de propriétés du projet..."), mais cela ne me génère toujours pas de calendll.lib !
    Justement : il n'en génère pas s'il n'y a pas de symboles exportés.
    La directive d'exportation ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifdef MYLIB_EXPORTS
        #define MYLIB_API __declspec(dllexport)
    #else
        #define MYLIB_API __declspec(dllimport)
    #endif
    Lorsque tu compiles ta DLL, tu dois définir la macro MYLIB_EXPORTS pour le projet. Par défaut, VS le fait pour toi lorsque tu crée un nouveau projet DLL.
    Il te faut ensuite déclarer tes variables / fonctions / classes ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    extern MYLIB_API int AGlobalVariable ;
     
    MYLIB_API int AnExportedFunction ( int param1, void* param2 ) ;
     
    class MYLIB_API AnExportedClass {
     ....
    } ;
    Citation Envoyé par ceugniet Voir le message
    Je ne sais pas ce que c'est que "ce qui est exporté" ! S'agit-il des variables globales de la librairie ? Si oui, je me suis contenté, comme dans le cas de la LIB, de mentionner comme "extern" les variables globales mentionnées dans le .h. Quant aux macros "NOMDELALIB_API" ??? Je suppose qu'il s'agit d'un fichier calendll.api (ma librairie s'appelle calendll.dll) ? Mais point de calendll.api nulle part !!!
    Non, justement, on n'exporte pas une fonction d'une DLL via un simple extern, cf. la première réponse.

    Citation Envoyé par ceugniet Voir le message
    C'est quoi "Dependancy Walker" ??? Je suppose que c'est un utilitaire qui devrait faire partie de VS ! Mais je n'ai rien de tel, en tous cas je ne sais pas où le chercher !
    Ici : http://www.dependencywalker.com/
    C'est un outil "à part", franchement indispensable si tu développes des DLL.

    Citation Envoyé par ceugniet Voir le message
    A moins que ce soit :
    #pragma comment(lib,calendll.lib")
    puisque VS devrait m'en créer une !!!
    Oui, ce sera le .LIB qu'il faudra importer, ou rendre le projet de l'exécutable dépendant du projet de la DLL via les dépendances de solution (bouton droit sur le projet de l'exécutable => "Dépendances" => cocher le projet de la DLL).

    Citation Envoyé par ceugniet Voir le message
    " librairie d'importation" ? C'est quoi ça ?
    La librairie (statique) qui permet d'importer les fonctions de la DLL. Sans elle, tu serais obligé d'utiliser les fonctions de chargement dynamique de Windows (LoadLibrary / GetProcAddress / FreeLibrary) pour CHAQUE fonction exportée, et tu ne pourrais pas importer ni variables globales, ni classes C++.

    Citation Envoyé par ceugniet Voir le message
    "C'est le but des macros "NOMDELALIB_API" déclarée automatiquement" ? Ca consiste en quoi "déclarer" quand c'est VS qui déclare ? Il crée un fichier ? Du code ? Où ça ?
    Il crée du code dans l'entête principal du projet DLL, lorsque tu génères un projet "DLL" via les assistants. Je te conseille de créer un nouveau projet de test en lui demandant de créer un projet DLL NON VIDE, de façon à voir ce qu'il met dedans.
    N'oublie pas de bien lire la : DLL en même temps.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  11. #11
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Bonjour,

    Me revoilà avec mes questions sans fin...

    J'ai bien essayé de créer une DLL mais jusqu'à présent sans succès. J'y reviendrai plus tard.

    En attendant, j'ai constaté que le cas que j'avais réussi sur une librairie statique était un cas très particulier : il n'y a avait pas de variables globales dans la librairie.

    J'ai essayé de créer une librairie statique parmi celles que j'ai déjà, et elle ne marche pas à cause des variables globales, précisément.

    Le fichier C:\0\1\p\vc\inc\codedfiles.h 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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    #ifdef creelib
    #ifndef codedh
    #define codedh
    #define bufsize 65536
    unsigned char ascbuf[bufsize];
    int ascnotread,ascfindefichier,asclus,ascnblig,ascadfichbuf,ascadundef;
    FILE *input_file;
    void feedbuf();
    void initread();
    int readlin(char *line);
    int readline(char *line);
    int readlin2(char *line,int *adfi);
    int readline2(char *line,int *adfi);
    #endif
    #else
    #ifndef codedh
    #define codedh
    #define bufsize 65536
    extern unsigned char ascbuf[bufsize];
    extern int ascnotread,ascfindefichier,asclus,ascnblig,ascadfichbuf,ascadundef;
    extern FILE *input_file;
    void feedbuf();
    void initread();
    int readlin(char *line);
    int readline(char *line);
    int readlin2(char *line,int *adfi);
    int readline2(char *line,int *adfi);
    #endif
    #endif
    Dans le "projet" "codedfiles", le fichier codedfiles.cpp contient quelque chose comme :

    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
     
    #define creelib
    #include "stdafx.h"
     
    void feedbuf()
    {
    ...
    }
    void initread()
    {
    ...
    }
    ... etc
    int readline2(char *line,int *adfi)
    {
    ...
    }
    et le fichier stdafx.h contient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #pragma once
     
    #include "targetver.h"
     
    #define WIN32_LEAN_AND_MEAN             // Exclure les en-têtes Windows rarement utilisés
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include "C:\0\1\p\vc\inc\codedfiles.h"
    Comme j'ai défini creelib dans codedfiles.cpp le fichier codedfiles.cpp interprète les variables ascnotread, ascfindefichier, etc... comme des variables internes.

    La création de la librairie ne pose apparemment pas de problème !

    Dependency walker (qui est censé marcher pour windows jusqu'à Vista - alors que mon système est Windows 7 - ) ne reconnaît cependant rien dans la librairie créée : il me dit
    No DOS or PE signature found. This is not a valid 32-bit or 64-bit Windows module.
    Peut-être ce logiciel n'est-il utilisé que pour les dll ! Mais bon !

    Je crée ensuite un "projet" testcoded. Dedans, le fichier stdafx.h contient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #pragma once
     
    #include "targetver.h"
     
    #include <stdio.h>
    #include <tchar.h>
    #include "C:\0\1\p\vc\inc\codedfiles.h"
    et le fichier testcoded.cpp contient :

    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
     
    #include "stdafx.h"
     
     
    #pragma comment(lib,"C:\\0\\1\\p\\vc\\lib\\crelibs\\codedfiles\\Debug\\codedfiles.lib")
    int _tmain(int argc, _TCHAR* argv[])
    {
    	   initread();
    	   input_file=fopen("\\0\\0\\garb\\bidon.txt","rb");
    	   int t;
    	   char myline[200];
    	   t=readline(myline);
    	   while (t==0)
    	   {
    		   printf("%s\n",myline);
    		   t=readline(myline);
    	   }
    	return 0;
    }
    A la génération, la réponse est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    1>codedfiles.lib(codedfile.obj) : error LNK2019: symbole externe non résolu "struct _iobuf * input_file" (?input_file@@3PAU_iobuf@@A) référencé dans la fonction "void __cdecl feedbuf(void)" (?feedbuf@@YAXXZ)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int ascfindefichier" (?ascfindefichier@@3HA)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int asclus" (?asclus@@3HA)
    ... etc
    au total sept symboles externes non résolus
    Alors, voilà ! Apparemment, je n'ai pas compris !

    Merci de m'aider encore un peu !

  12. #12
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par ceugniet Voir le message
    Le fichier C:\0\1\p\vc\inc\codedfiles.h 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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    #ifdef creelib
    #ifndef codedh
    #define codedh
    #define bufsize 65536
    unsigned char ascbuf[bufsize];
    int ascnotread,ascfindefichier,asclus,ascnblig,ascadfichbuf,ascadundef;
    FILE *input_file;
    void feedbuf();
    void initread();
    int readlin(char *line);
    int readline(char *line);
    int readlin2(char *line,int *adfi);
    int readline2(char *line,int *adfi);
    #endif
    #else
    #ifndef codedh
    #define codedh
    #define bufsize 65536
    extern unsigned char ascbuf[bufsize];
    extern int ascnotread,ascfindefichier,asclus,ascnblig,ascadfichbuf,ascadundef;
    extern FILE *input_file;
    void feedbuf();
    void initread();
    int readlin(char *line);
    int readline(char *line);
    int readlin2(char *line,int *adfi);
    int readline2(char *line,int *adfi);
    #endif
    #endif
    Cet entête n'a pas de sens : tu définis en compilation conditionnelle deux fois la même chose, tu n'utilises pas les directives d'exportation normales des DLL.

    Je t'écrivais que VS allait générer un code similaire à celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifdef MYLIB_EXPORTS
        #define MYLIB_API __declspec(dllexport)
    #else
        #define MYLIB_API __declspec(dllimport)
    #endif
    Ce n'est PAS un oubli de ma part de ne pas avoir mis de code "utile" dans ce #ifdef : il ne contient bien QUE des #define, et rien d'autre !
    Le code que je citais ensuite te montrait où (et comment !) utiliser la macro MYLIB_API dans tes déclarations de variables globales / fonctions / classes.

    Crée un projet DLL tout neuf, SANS cocher la case "Projet vide" de l'assistant, et regarde bien ce que génère Visual Studio comme code.



    Note : Dependancy Walker ne fonctionne PAS sur les librairies statiques. Il ne peut analyser que les exécutables et les librairies dynamiques.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  13. #13
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Merci de ta réponse, une fois de plus très rapide.

    Mais je crois que l'on ne s'est pas compris. J'ai dit en tête que je laissais de côté, pour l'instant, les DLL. Je veux juste comprendre complètement comment on crée une librairie statique (j'ai bien compris que Dependency Walker ne me sera alors d'aucune utilité).
    Cet entête n'a pas de sens : tu définis en compilation conditionnelle deux fois la même chose, tu n'utilises pas les directives d'exportation normales des DLL.
    (pour les directives des DLL, c'est donc normal, puisqu'ici, c'est une librairie statique)

    Les deux ifs imbriqué ont pour moi la signification suivante :

    Si le parametre creelib existe, alors, je veux compiler seulement la première partie, celle qui définit les variables comme internes, et sinon, je veux compiler seulement la deuxième partie, celle qui définit les variables comme externes. Comme j'ai défini creelib dans le programme qui crée la librairie, je pensais que les variables seraient internes. Et comme je ne définis pas creelib dans le programme test (qui UTILISE cette librairie), ces variables doivent être considérées comme externes, non ? C'est ce que je voulais en tous cas.
    Ensuite, le deuxième if (#ifdef codedh) était là parce que je voulais éviter que l'on passe deux fois sur le même code si jamais le fichier codedfiles.h était lu deux fois (j'avais eu cette impression...).

    Ce n'est PAS un oubli de ma part de ne pas avoir mis de code "utile" dans ce #ifdef : il ne contient bien QUE des #define, et rien d'autre !
    Veux-tu dire que c'est interdit de mettre du code "utile" dans un if ?

  14. #14
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par ceugniet Voir le message
    Les deux ifs imbriqué ont pour moi la signification suivante :

    Si le parametre creelib existe, alors, je veux compiler seulement la première partie, celle qui définit les variables comme internes, et sinon, je veux compiler seulement la deuxième partie, celle qui définit les variables comme externes. Comme j'ai défini creelib dans le programme qui crée la librairie, je pensais que les variables seraient internes. Et comme je ne définis pas creelib dans le programme test (qui UTILISE cette librairie), ces variables doivent être considérées comme externes, non ? C'est ce que je voulais en tous cas.
    Non. Pour définir une VARIABLE comme "exportée" de ta librairie, tu mets la directive extern devant, c'est tout, et c'est le MÊME entête utilisé "en interne" et "en externe".
    Pour une exporter une fonction, tu n'as RIEN à définir de particulier dans le cas d'une librairie statique.

    Citation Envoyé par ceugniet Voir le message
    Ensuite, le deuxième if (#ifdef codedh) était là parce que je voulais éviter que l'on passe deux fois sur le même code si jamais le fichier codedfiles.h était lu deux fois (j'avais eu cette impression...).
    C'est ce que l'on appelle communément la "directive anti-double inclusion". Elle se met au niveau le plus externe, quoi qu'il arrive.

    Ton entête doit donc s'écrire ainsi (pense aux indentations / lignes de séparation pour rendre tout ça plus lisible) :
    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
    #ifndef __codedh__
    #define  __codedh__
     
    #define bufsize 65536
     
    extern unsigned char ascbuf[bufsize];
    extern int ascnotread,ascfindefichier,asclus,ascnblig,ascadfichbuf,ascadundef;
    extern FILE *input_file;
     
    void feedbuf();
    void initread();
    int readlin(char *line);
    int readline(char *line);
    int readlin2(char *line,int *adfi);
    int readline2(char *line,int *adfi);
     
    #endif //  __codedh__
    Normalement, c'est bon avec ça.

    Citation Envoyé par ceugniet Voir le message
    Veux-tu dire que c'est interdit de mettre du code "utile" dans un if ?
    Bien sûr que non ! Mais pour les directives d'exportation d'une DLL, le cas par défaut est de ne PAS le faire. C'est la directive "MYLIB_API" qui sera définie différemment suivant que tu exportes (compilation de la DLL) ou que tu importes (utilisation de la DLL), mais les prototypes des fonctions / variables / classes ne changent pas, et n'ont donc pas besoin d'être définis "différemment" d'un mode à l'autre.

    Pour une librairie statique, il n'y a aucune différence entre les deux modes.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  15. #15
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Merci, j'essaye !

  16. #16
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    Ben mes variables sont toujours non définies .

    1>Édition des liens en cours...
    1>testcoded.obj : error LNK2001: symbole externe non résolu "struct _iobuf * input_file" (?input_file@@3PAU_iobuf@@A)
    1>codedfiles.lib(codedfile.obj) : error LNK2019: symbole externe non résolu "struct _iobuf * input_file" (?input_file@@3PAU_iobuf@@A) référencé dans la fonction "void __cdecl feedbuf(void)" (?feedbuf@@YAXXZ)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int ascfindefichier" (?ascfindefichier@@3HA)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int asclus" (?asclus@@3HA)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int ascadfichbuf" (?ascadfichbuf@@3HA)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "unsigned char * ascbuf" (?ascbuf@@3PAEA)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int ascadundef" (?ascadundef@@3HA)
    1>codedfiles.lib(codedfile.obj) : error LNK2001: symbole externe non résolu "int ascnotread" (?ascnotread@@3HA)
    1>C:\0\1\p\visual\vc\testcoded\Debug\testcoded.exe : fatal error LNK1120: 7 externes non résolus
    1>Le journal de génération a été enregistré à l'emplacement "file://c:\0\1\p\visual\vc\testcoded\testcoded\Debug\BuildLog.htm"
    1>testcoded - 9 erreur(s), 1 avertissement(s)
    ========== Génération*: 0 a réussi, 1 a échoué, 0 mis à jour, 0 a été ignoré ==========
    Je suppose que j'ai encore oublié quelque chose !

Discussions similaires

  1. Utiliser une bibliothèque statique ?
    Par divide dans le forum Débuter
    Réponses: 1
    Dernier message: 05/12/2012, 14h25
  2. Réponses: 0
    Dernier message: 06/02/2009, 22h08
  3. Réponses: 1
    Dernier message: 26/09/2007, 17h16
  4. Réponses: 1
    Dernier message: 18/06/2007, 16h10
  5. Utiliser une bibliothèque statique
    Par djflex68 dans le forum MFC
    Réponses: 6
    Dernier message: 15/08/2005, 19h26

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