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 :

Windows, Qt, const char* et const WCHAR*


Sujet :

C++

  1. #1
    Membre confirmé Avatar de Narann
    Inscrit en
    Juin 2007
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 140
    Par défaut Windows, Qt, const char* et const WCHAR*
    Salut à tous,

    Je bosse actuellement sur l'UI windows de mupen64plus (pour ceux qui connaissent).

    Je rencontre une difficulté avec les conversion de type...

    Je vous explique, voici une fonction C tiré de l'UI console du projet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
    {
        if (pccProcedureName == NULL)
            return NULL;
     
        return GetProcAddress(LibHandle, pccProcedureName);
    }
    GetProcAddress renvoit donc un void*.

    Quand on compile en Visual Studio (le projet windows est en Visual Studio), ça fonctionne. Pas de problèmes.


    Moi je bosse sur l'interface graphique qui est en Qt4. J'utilise donc qmake et mingw32-make pour compiler.

    Nous avons besoins, pour cette UI de faire grosso mode la même chose que pour l'interface console: Charger la lib mupen64plus.dll, qui contient le "core" de l'émulateur.

    Voici la méthode:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void * LibraryLoader::resolve(const char * name)
    {
        if (!private_->pluginHandle)
            return 0;
     
        return GetProcAddress(private_->pluginHandle, name);
    }
    Avec comme définition pour pluginHandle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m64p_dynlib_handle pluginHandle;
    Et là, ça crash avec ça comme message:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    src\libraryloader_win32.cpp:34: error: invalid conversion from 'int (*)()' to 'void*'
    En lisant la doc msdn: http://msdn.microsoft.com/en-us/libr...=VS.85%29.aspx
    Il est précisé que GetProcAddress renvoit l'adresse de la fonction ou variable exporté.
    Serait-ce une subtilisé du compilo?

    Visual Studio renverrait bien l'adresse (ça expliquerai pourquoi l'UI console compile sans problème), et mingw32 renverrait un int? C'est possible ça?

    Si l'un d'entre vous pourrait éclairer la lanterne? Parce que là je suis dans l'impasse.

    Merci d'avance et bonne journée à tous!

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Le message me semble plutot claire :
    La conversion entre l'adresse de la fonction (qui doit être du type int ()) et un void* n'est pas acceptée. Visual Studio doit faire cette conversion implicitement mais g++ demande un cast.

    De plus, il me semble que la norme ne garantit pas la conversion d'un pointeur de fonction vers un void* bien que g++ l'accepte.

    Pourquoi ne pas définir ta fonction comme renvoyant un int(*)() ?

    Bien sur, si tu souhaites que ton code compile sur Visual et mingw ou g++, tu peux aussi faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    return (void*)GetProcAddress(private_->pluginHandle, name);
    ou encore :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return static_cast<void*>(GetProcAddress(private_->pluginHandle, name));//Ou reinterpet cast (je ne sait jamais).

  3. #3
    Membre confirmé Avatar de Narann
    Inscrit en
    Juin 2007
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 140
    Par défaut
    Hello! Tout déja merci pour cette réponse! Je vais regarder comment on fait un cast (d'ailleurs si tu avais grosso modo la ligne que ça pourrait donner...)

    De plus, il me semble que la norme ne garantit pas la conversion d'un pointeur de fonction vers un void* bien que g++ l'accepte.
    Bon, dans les fait c'est un HMODULE, mais ça ne résout pas mon soucis.

    Pourquoi ne pas définir ta fonction comme renvoyant un int(*)() ?
    Haha et c'est la que c'est drôle (ou pas...). La définition des procédure de chargement des dynlibs sont communes entre Unix et Windows... C'est juste que dans mon .pro (QT) j'ai (en gros):

    HEADERS += include/libraryloader.h
    unix:SOURCES += src/libraryloader_unix.cpp
    win32:SOURCES += src/libraryloader_win32.cpp
    Ça marche sous Linux. Et sous Windows (Visual Studio) aussi. Mais pas avec mingw32-make...

    EDIT: Je suis en train de prévisualisé mon message et je vois que tu a édité le tiens avec un exemple.

    Je vais le tester et je te redis, merci beaucoup!

  4. #4
    Membre confirmé Avatar de Narann
    Inscrit en
    Juin 2007
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 140
    Par défaut
    Bon:
    return static_cast<void*>(GetProcAddress(private_->pluginHandle, name));
    Ne fonctionne pas.

    Par contre, avec :
    return (void*)GetProcAddress(private_->pluginHandle, name);
    Ça compile!

    Le soucis c'est que ça se lance mais ça crash windows. Etant sous QT + MinGW, je suis incapable de débugger le truc. va falloir que j'y aille au printf...

    Même si j'ai un problème, on peut dire que le sujet est résolu...

    Merci beaucoup!


  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Il me semble que GetProcAdress s'utilise avec la signature de la fonction que tu veux récupérer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    typedef int(*t_pfn_proc)() 
    t_pfn_proc osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName)
    {
        if (pccProcedureName == NULL)
            return NULL;
     
        return (t_pfn_proc)GetProcAddress(LibHandle, pccProcedureName);
    }
    Ou idéalement avec une version générique (et des std::string à la place de ces affreux char*) :
    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
    template<class T>
    void osal_dynlib_getproc(m64p_dynlib_handle LibHandle, std::string const &name_, T&pf_)
    {
        pf_ =(T)GetProcAddress(LibHandle, name_.c_str());
    }
     
    int main()
    {
        int (*pf)();
        osal_dynlib_getproc(0,0,pf);
        if(pf){
        pf();
        }
        return 0;
    }
    J'avoue que le retour en void* me fait un peu tiquer.

  6. #6
    Membre confirmé Avatar de Narann
    Inscrit en
    Juin 2007
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 140
    Par défaut
    Ok, merci, je vais regarder ça!
    J'avoue que le retour en void* me fait un peu tiquer.
    Bon, en fait, c'est du multiplateforme.
    Le type est défini dans un header du projet (après, peut être que le m64p_types.h n'est pas bon... Mais le projet fonctionne):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #ifdef WIN32
    #define HINSTANCE* m64p_dynlib_handle;
    #ifdef UNIX
    #define void* m64p_dynlib_handle;
    (dsl je suis au taf, je ne me rappel plus de la syntax exact).
    Donc sous Windows, le pointeur est supposé être de type HINSTANCE. Je vais tenter ça aussi...

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Narann Voir le message
    Ok, merci, je vais regarder ça!

    Bon, en fait, c'est du multiplateforme.
    Le type est défini dans un header du projet (après, peut être que le m64p_types.h n'est pas bon... Mais le projet fonctionne):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #ifdef WIN32
    #define HINSTANCE* m64p_dynlib_handle;
    #ifdef UNIX
    #define void* m64p_dynlib_handle;
    (dsl je suis au taf, je ne me rappel plus de la syntax exact).
    Donc sous Windows, le pointeur est supposé être de type HINSTANCE. Je vais tenter ça aussi...
    Je pensais au type retour de ta fonction : void * LibraryLoader::resolve. Pourquoi ne pas retourner directement le pointeur de fonction bien typé ?

  8. #8
    Membre confirmé Avatar de Narann
    Inscrit en
    Juin 2007
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 140
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Pourquoi ne pas retourner directement le pointeur de fonction bien typé ?
    Je suppose que c'est parce que la fonction resolve renvoit des fonctions qui elles même renvois différents types de valeur...

    Enfin je suppose...

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Justement avec une approche générique, tu peux avoir un typage fort plus rapidement.

  10. #10
    Membre confirmé Avatar de Narann
    Inscrit en
    Juin 2007
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 140
    Par défaut
    Merci pour cette réponse. Je n'ai pas tout compris.
    Mais si vous avez le temps (ou un simple lien), je suis preneur.

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Narann Voir le message
    Merci pour cette réponse. Je n'ai pas tout compris.
    Mais si vous avez le temps (ou un simple lien), je suis preneur.
    C'était l'exemple que je proposais plus haut :
    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
    template<class T>
    void osal_dynlib_getproc(m64p_dynlib_handle LibHandle, std::string const &name_, T&pf_)
    {
        pf_ =(T)GetProcAddress(LibHandle, name_.c_str());
    }
     
    int main()
    {
        int (*pf)();
        osal_dynlib_getproc(0,0,pf);
        if(pf){
        pf();
        }
        return 0;
    }
    La fonction est directement récupérée avec le bon type.

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

Discussions similaires

  1. Réponses: 12
    Dernier message: 03/09/2009, 03h06
  2. Conversion de char vers const char
    Par Lucas Panny dans le forum Visual C++
    Réponses: 9
    Dernier message: 01/09/2008, 16h36
  3. Convertir un (char *) en (const char *) dans C++
    Par anas.eh dans le forum C++
    Réponses: 10
    Dernier message: 03/09/2007, 13h59
  4. Convertir un "char" en "CONST char"
    Par N3odyme dans le forum C
    Réponses: 3
    Dernier message: 17/08/2006, 19h48
  5. const char et const unsigned char
    Par moon93 dans le forum C
    Réponses: 8
    Dernier message: 04/08/2006, 15h59

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