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

Les *.dll et les *.so !


Sujet :

C

  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut Les *.dll et les *.so !


    Je sais, question récurrente dans ce forum mais peut-être pas plus que ça aller hop j'me lance

    Je sais que sous Windows on déclare/définit et appel les fonctions partagées comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    __declspec(dllexport) int Fonction(void)
    Est-ce exact ? Des précisions peut-être à ce niveau ? Je débute complètement dans le domaine des DLL Si c'est ok pour Windows passons aux Unixoïdes, y a-t-il des choses à savoir à ce sujet ? Un équivalent à __declspec(dllexport) ?


  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Ne connaissant pas la version Linux, j'ai fait une première ébauche de constante pour faciliter l'écriture, comme j'ai souvent vu dans ce genre de cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifndef DECLSPEC
    #  if defined(GNUC)
    #     define DECLSPEC
    #  elif defined(MINGW)
    #     define DECLSPEC __declspec(dllexport)
    #  endif
    #endif

  3. #3
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Bonjour,

    L'approche windows et l'approche *nix diffèrent totalement sur ce point. En windows tout ce qui n'est pas déclaré comme étant visible de l'extérieur est caché, en unix tout ce qui n'est pas déclaré comme étant caché est visible de l'extérieur
    Ensuite cela va aussi dépendre de ta chaîne de compilation, il y a en gros trois cas (je ne passe pas en revue les cas de cross compilation) :

    1. compilateur microsoft, tu génères une DLL pour windows sous windows
    2. gcc+binutils, tu génères un so pour linux sous linux
    3. gcc+binutil, tu génères une DLL pour windows sous windows


    Le cas 1 nécessite l'utilisation des __declspec avec comme arguments dllimport/dllexport, le cas 3 aussi mais avec la syntaxe gcc ; le cas 2 ne nécessiterait rien de particulier mais on peut utiliser les attributs de visibilité proposés par gcc pour avoir un comportement similaire.

    L'approche usuelle pour gérer du code unique pour tous ces cas est de définir des macros API_PUBLIC et API_HIDDEN utilisées pour marquer les fonctions de ton API. Elles devront en plus avoir une définition différente lors de la construction de la bibliothèque et lors de son utilisation. Du coup il faudra définir une autre macro (BUILDING_MY_LIB) uniquement lors de la construction de la bibliothèque (pour pouvoir choisir en dllimport et dllexport).
    Cela pourrait donner quelquechose 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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #if defined defined _WIN32 || defined __CYGWIN__
            /* On est sous windows, reste à déterminer le compilateur utilisé */
    #  if defined BUILDING_MY_LIB
            /* On construit la bibliothèque -> on va exporter les symboles*/
    #    if defined _MSC_VER
            /* compilateur microsoft */
    #      define API_PUBLIC __declspec(dllexport)
    #      define API_HIDDEN
    #    elif defined __GNUC__
            /* gcc sous windows = mingw/cygwin, mais aussi icc (je crois) */
    #      define API_PUBLIC __attribute__((__dllexport__))
    #      define API_HIDDEN
    #    else
            /* autre compilateur : vaut mieux tout arrêter */
    #      error "Unsupported compiler"
    #    endif
     
    #  else /* NOT BUILDING_MY_LIB */
            /* On utilise la bibliothèque : on importe les symboles */
    #    if defined _MSC_VER
    #      define API_PUBLIC __declspec(dllimport)
    #      define API_HIDDEN
    #    elif defined __GNUC__
    #      define API_PUBLIC __attribute__((__dllimport__))
    #      define API_HIDDEN
    #    else
    #      error "Unsupported compiler"
    #    endif
     
    #  endif /* BUILDING_MY_LIB */
     
     
    #else /* NOT FOR WINDOWS */
     
    #  define API_PUBLIC __attribute__(( __visibility__ ("default") ))
    #  define API_HIDDEN __attribute__(( __visibility__ ("hidden") ))
     
    #endif /* Platform selection */
    Ensuite dans un header exporté tu pourras les utiliser ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #ifndef MONHEADER_H__
    ...
    API_PUBLIC void ma_super_fonction(int, const char*);
    ...
    Dans un header non exporté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #ifndef INTERNHEADER_H
    #define  INTERNHEADER_H
     
    #ifndef BUILDING_MY_LIB
    #  error "Only for internal use"
    #endif
     
    API_HIDDEN void fonction_visible_en_interne();
    API_PUBLIC void ma_super_fonction(int, const char*);
    Et dans un source quelconque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    API_HIDDEN static void fonction_visible_de_nulle_part();
    API_HIDDEN void fonction_visible_en_interne();
    Voilà en gros la démarche usuelle utilisée

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    __attribute__
    __dllexport__
    __dllimport__
    __visibility__
    Ils sont définis quelque part je suppose dans les bibliothèques utilisées par le compilateur ou le système ?

    Qu'entend-tu par header exporté ou non exporté ?

  5. #5
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    __attribute__
    __dllexport__
    __dllimport__
    __visibility__
    Ils sont définis quelque part je suppose dans les bibliothèques utilisées par le compilateur ou le système ?

    Qu'entend-tu par header exporté ou non exporté ?
    Ce sont des extensions gcc, il faut peut-être faire attention à la version du gcc utilisé et des binutils ... disons que pour une distrib linux récentre (avec gcc 4 ou +) il n'y aura pas de problèmes.
    Pour être un peu plus complet il faudrait remplacer la fin des defines par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #else /* NOT FOR WINDOWS */
    #  if __GNUC__ >= 4
    #    define API_PUBLIC __attribute__(( __visibility__ ("default") ))
    #    define API_HIDDEN __attribute__(( __visibility__ ("hidden") ))
    #  else /* __GNU_C__ < 4 */
    #    define API_PUBLIC
    #    define API_HIDDEN
    #  endif /* __GNUC__ >= 4 */
    #endif /* Platform selection */

    C'est vrai que mes termes ne sont pas adéquats
    Disons que ça dépend de l'architecture de ton environnement de construction. J'aurais du parler de headers distribués et de headers internes.
    L'utilisateur final de ta bibliothèque n'aura que la bibliothèque, celui qui désire développer avec ta bibliothèque aura la bibliothèque et les headers qui décrivent l'api (donc des headers qui ne devront pas utiliser API_HIDDEN a priori) -> headers distribués incorrectement appelés exportés.
    Mais tu peux avoir besoin lors de la construction de ta bibliothèque d'autres headers qui ne seront jamais distribués qui eux pourront comporter des API_HIDDEN -> headers internes incorrectement appelés non exportés.

  6. #6
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Ok c'est plus clair maintenant pour ton exemple que je vais reprendre si tu le permet et surtout pour tes explications

  7. #7
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Ok c'est plus clair maintenant pour ton exemple que je vais reprendre si tu le permet et surtout pour tes explications
    Bah oui C'est fait pour
    Bon courage !

  8. #8
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Citation Envoyé par kwariz Voir le message
    Bah oui C'est fait pour
    Bon courage !

  9. #9
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Juste une dernière question qui viens de me venir à l'esprit, les constantes comme sont définit quelques part au préalable suivant le compilateur utilisé ou bien il faut le faire soi-même dans les options de compilation ?

  10. #10
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Juste une dernière question qui viens de me venir à l'esprit, les constantes comme sont définit quelques part au préalable suivant le compilateur utilisé ou bien il faut le faire soi-même dans les options de compilation ?
    La plupart sont définies par le compilateur par défaut ou en fonction des paramètres donnés lors de la compilation, de l'environnement de compilation et/ou d'exécution, des bibliothèques utilisées ...
    Il y a un wiki qui recense tout ça : Pre-defined C/C++ Compiler Macros.

  11. #11
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Ok

  12. #12
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    J'ai un petit soucis, en sachant que je suis sur Code::Block donc MingW j'obtiens ceci comme message
    C:\Projects\BEngine\BLib\BLib_stack.c|63|warning: '__dllexport__' attribute ignored [-Wattributes]|
    C:\Projects\BEngine\BLib\BLib_stack.c|63|error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token|
    ||=== Build finished: 1 errors, 1 warnings (0 minutes, 0 seconds) ===|
    et le code en question
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    API_PUBLIC b_stack * b_stack_new (void)
    {
       return NULL;
    }

  13. #13
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Que contient API_PUBLIC ?

  14. #14
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Vu mon OS et mon compilateur cela devrait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    __attribute__((__dllexport__))

  15. #15
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Et ça l'est réellement si tu l'imprimes ?

  16. #16
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Tu l'imprimes comment ?

  17. #17
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Deux solutions :
    Soit tu stringifies la macro et sa valeur pour l'imprimer normalement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #define str(x) #x
    #define xstr(x) str(x)
    #define PRINT_MACRO(x) puts(#x "=" xstr(x))
    ....
     
    /* là où il faut dans une portion de code */
      PRINT_MACRO(API_PUBLIC);
    On peut aussi l'afficher comme message lors de la compilation si tu veux (avec un pragma message ...)


    Soit tu lances un gcc -E -dM source.c pour avoir la liste de toutes les macros (mais vraiment toutes, la liste peut être longue) définies après le preprocessing de source.c.

    Mes exemples plus haut (avec les #define suivant le compilo et l'OS et la phase de build) sont tapés à la volée et peuvent ne pas être corrects


    EDIT: pour l'affichage lors de la phase de compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define DO_PRAGMA(x) _Pragma(#x)
    #define COMPILE_PRINT_MACRO(x) DO_PRAGMA(message (#x "=" xstr(x)))
     
    #define API_PUBLIC __attribute__(( __dllexport__ ))
    COMPILE_PRINT_MACRO(API_PUBLIC)
    te donnerait ce message lors de la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    main.c:10:1: note: #pragma message: API_PUBLIC=__attribute__(( __dllexport__ ))

  18. #18
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    C:\Projects\BEngine\BLib\BLib_main.h|74|warning: malformed '#pragma message', ignored [-Wpragmas]|

  19. #19
    Membre expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Points : 3 352
    Points
    3 352
    Par défaut
    Quelle version de gcc utilises-tu ?

  20. #20
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    GCC Compiler (version 4.7.1, 32 bit). Celui fournit avec C::B en fait dans sa dernière version.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [WD14] Windev les API et les DLL en VB et C++
    Par devalender dans le forum WinDev
    Réponses: 2
    Dernier message: 14/09/2009, 18h57
  2. [C#] [UserControl] [dll] Integrer les dll.
    Par maxdwarf dans le forum Windows Forms
    Réponses: 5
    Dernier message: 13/02/2008, 13h08
  3. Comment retrouver les Dll ou les OCX suivantes?
    Par nnj dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 26/08/2007, 13h18

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