IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Fonction membre statique


Sujet :

C++Builder

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut Fonction membre statique
    Bonjour,

    J'ai un composant qui utilise une classe importée. L'interface de la classe était de type COM.
    Le classe en question génère des évènements. Mon composant doit les récupérer, mettre en forme les messages et renvoyer le tout dans un autre évènement.
    Seulement, j'ai un gros problème que je ne sais pas résoudre.
    La classe est écrite en C# et l'évènement est un delegate.
    J'ai créé une fonction intermédiaire pour pouvoir utiliser ce delegate mais je doit envoyer une information pour que la classe puisse appeler ma fonction.
    Voici un exemple d'appel que j'ai dans C++Builder :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClasseExterne->OnActioncallbackWrapper((long)&BackFromActioncallbackWrapper);
    Et voici comment ma fonction est implanté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void TMonComp::BackFromActioncallbackWrapper(IAsyncResult* asyncResult_in)
    VARIANT value;
    asyncResult_in->get_AsyncState(&value);
    if (FOnAction)
       {
       (FOnAction)(this, VarToStr(value));
       }
    Et dans l'entête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static void BackFromAtioncallbackWrapper(IAsyncResult* asyncResult_in);
    Le problème :
    - Si je laisse la foncion en static, elle n'a plus accès au pointeur this et je ne peut pas remonter l'information dans l'évènement.
    - Si j'enlève le mot static, j'ai l'erreur suivante :
    [BCC32 Erreur] TMonComp.cpp(85): E2031 Impossible de transtyper de 'void (* (_closure )(IAsyncResult *))(IAsyncResult *)' en 'long'


    Quelqu'un à une idée lumineuse ?

    Merci

  2. #2
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    J'ai pu avancé mais je bloque toujours.

    J'ai un nouveau type d'évènement : (.h)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef void __fastcall (__closure *TNotifyString)(UnicodeString Text);
     
    ...
     
    static TNotifyString FOnAction;
    Et j'ai donc modifié le code : (.cpp)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void TMonComp::BackFromAtioncallbackWrapper(IAsyncResult* asyncResult_in)
    {
    VARIANT value;
    asyncResult_in->get_AsyncState(&value);
    if (FOnAction)
       {
       (FOnAction)(VarToStr(value));
       }
    }
    Seulement, j'ai une erreur lors de l'édition des liens :
    [ILINK32 Erreur] Error: 'TMonComp::FOnAction' externe non résolu, référencé depuis C:\DOCUMENTS AND SET...\DEBUG\TMONCOMP.OBJ
    J'ai vu dans la FAQ C++ qu'il faut initialiser les membres static pour corriger cette erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //---------------------------------------------------------------------------
    void __fastcall TMonComp::foo(UnicodeString Text)
    {
    //
    }
    J'ai essayé ces 2 lignes et cela ne corrige pas l'erreur, j'en ai 3 autres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TSpeech::FOnAction = (TNotifyString)&foo;
    TSpeech::FOnAction = NULL;
    [BCC32 Erreur] TMonComp.cpp(15): E2303 Nom de type attendu
    [BCC32 Erreur] TMonComp.cpp(15): E2356 Mauvaise correspondance de type dans la redéclaration de 'TMonComp::FOnAction'
    [BCC32 Erreur] TMonComp.h(24): E2344 Déclaration plus récente de 'TMonComp::FOnAction'
    Une idée ?

  3. #3
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    J'ai pu identifier plus précisément le problème.
    Il intervention quand j'utilise le TNotifyString (qui est en static) dans la fonction static.
    Si j'utilise cette donnée membre dans une autre fonction, il n'y a aucun problème.

    Donc, je me retrouve avec une fonction static d'une classe qui provoque une erreur de lieur quand elle accède à une donnée static de sa propre classe.


    Je coule.

    Dois-je plutôt demander dans le forum c++ si ce n'est pas une erreur spécifique de C++Builder ? Parce que je n'en sais rien.

  4. #4
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Par défaut
    Hello,

    Et avec ceci ??
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TNotifyString TSpeech::FOnAction = (TNotifyString)&foo;
    ou
    TNotifyString TSpeech::FOnAction = NULL;

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Par défaut
    Je n'ai pas très bien compris ton problème: tu as une classe C++ qui récupère un événement généré par une classe C# reçue depuis une interface COM. C'est bien ça?

    Tu aimerais que chaque instance de la classe C# appelle la fonction TMonComp::BackFromAtioncallbackWrapper de l'instance de TMonComp correspondante? Ou as-tu une seule instance de TMonComp qui répond à tous les événements de toutes les instance de la classe C#?

    Si tu t'oriente vers une solution avec une fonction statique, cela semble signifier que tu utilises la même fonction de traitement C++ pour toutes les instances de la classe C# (le second cas de mon raisonnement compliqué ci-dessus). Dans ce cas, tu devrais aussi pouvoir travailler avec une fonction et une variables globales:

    .h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    extern TMonComp* FActionObject;
    void BackFromAtioncallbackWrapper(IAsyncResult* asyncResult_in);
    .cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    TMonComp* FActionObject=NULL;  // Initialisation de l'objet à appeler
     
    // Cette fonction ne sert qu'à appeler le callback de l'instance
    void BackFromAtioncallbackWrapper(IAsyncResult* asyncResult_in) {
      VARIANT value; 
      asyncResult_in->get_AsyncState(&value);
      if (FActionObject)
      {
        FActionObject->CallbackFunction(VarToStr(value));
      }
    }
    Et dans ton TMonComp.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class TMonComp {
     
      public:
         void CallbackFunction(UnicodeString Text);
     
    };
    TMonComp.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void TMonComp::CallbackFunction(UnicodeString Text)
    {
    ...
    }
    Il faut ensuite que tu assignes une instance de TMonComp à FActionObject pour qu'elle puisse traiter le message. Ici, j'
    J'espère avoir apporté un peu d'eau à ton moulin ;-)

  6. #6
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    Merci de votre aide.

    @totoche76 : Ça ne fonctionne pas. Une histoire d'erreur de transtypage.
    De toute façon, maintenant l'erreur se produit au moment de lier (ilink32) et est provoqué par cette partie du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void TMonComp::BackFromAtioncallbackWrapper(IAsyncResult* asyncResult_in)
    {
    VARIANT value;
    asyncResult_in->get_AsyncState(&value);
    if (FOnAction) // provoque l'erreur
       {
       (FOnAction)(VarToStr(value)); // et la aussi
       }
    }
    J'utilise FOnAction dans une autre fonction et cela ne pose pas de problème. FOnAction et BackFromAtioncallbackWrapper sont static et devrait pouvoir se voir.
    En gros, je peux remplir la donnée mais je ne peux pas l'utiliser quand j'en ai besoin.

    @Patrick Seuret :
    Il peut y avoir plusieurs instance de mon composant. Le fait d'indiquer un évènement va donc appeler une fonction de la librairie C# qui va ajouter l'évènement à la liste des évènements devant être lancé. Donc, peu importe que l'évènement ou la fonction dans le composant soit statique ou non puisqu'une fois rempli, l'évènement est dans la liste.

    Seulement, pour appeler la fonction en question, il me faut impérativement une fonction que la librairie C# puisse appelé a travers le wrapper COM. Et je ne peut pas utiliser une fonction standard d'une classe à cause du pointeur this qu'il ne peut pas remplir. D'ailleurs, j'ai pas le choix à ce niveau.
    Je n'ai pas tout à fait compris ta solution avec une fonction globale.
    Tu veux dire qu'il faudrait qu'il y ai une fonction extérieure à ma classe qui soit utilisé et qui utiliserai une instance du composant ?
    Comment faire dans ce cas pour être sûr qu'il utilise le composant que je veux et non pas un autre ?

    Merci de votre aide

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Par défaut
    Citation Envoyé par gandf Voir le message
    Comment faire dans ce cas pour être sûr qu'il utilise le composant que je veux et non pas un autre ?
    C'est justement la question: si tu as plusieurs instances de ton composant, tu vas avoir de la peine à traiter un événement avec une fonction statique puisque par définition elle est partagée par toutes les instances. Je pensais donc que tu n'avais qu'une seule instance de TMonComp, c'est pourquoi je proposais de mettre une fonction globale (hors de la classe) qui utilise un pointeur global sur l'unique instance de TMonComp.

    Si ce n'est pas le cas, tu vas devoir trouver un système pour définir une fonction différente pour chaque instance de ton TMonComp et transmettre cette fonction comme delegate à la classe C#.

    Si tu connais le nombre maximum d'instance et qu'il est suffisament faible, tu peux créer autant de fonctions (globales ou statique, c'est kif-kif): la fonction1 appelle l'instance1 (enregistrée dans un tableau global par exemple), la fonction2 l'instance2, etc.
    A l'utilisation, il te faudra:
    1) mettre en place un système "n" qui te permet de savoir quelle est la prochaine fonction libre (un compteur ou un tableau des positions libres),
    2) sauver le pointeur de l'instance "n" correspondant dans le tableau à la position "n"
    3) tranmettre l'adresse de la fonction "n" à ton instance C#
    4) mettre à jour ton système de disponibilités (point 1)
    C'est un peu lourdaud mais ça devrait marcher si tu n'as pas 10'000 instances! En plus il faut gérer si tu as des instances qui doivent être retirées de la liste (tableau des positions libres ou réorganisation de la liste selon ce que ta classe C# te permet)

    En fait l'idéal serait de créer des "fonctions" dynamiquement (comme pour les instances), mais je ne pense pas que ce soit possible directement en C++.

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

Discussions similaires

  1. Variable statique locale à une fonction membre
    Par oodini dans le forum Langage
    Réponses: 36
    Dernier message: 26/11/2011, 23h00
  2. Réponses: 10
    Dernier message: 31/03/2010, 23h34
  3. Boost thread avec fonction membre non statique.
    Par Klaim dans le forum Boost
    Réponses: 2
    Dernier message: 11/08/2007, 02h58
  4. Réponses: 5
    Dernier message: 12/01/2005, 20h58
  5. Thread avec une fonction membre d'une classe
    Par SteelBox dans le forum Windows
    Réponses: 6
    Dernier message: 01/03/2004, 01h15

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