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 :

dllimport mode d'emploi?


Sujet :

C++Builder

  1. #1
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut dllimport mode d'emploi?
    Bonjour

    Je n'arrive pas à déclarer correctement une fonction du programme principal appelé dans une Dll
    La fonction appelée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    __declspec (dllexport) std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
    Je ne crois pas pertinent de déclarer une fonction de l'exécutable principal comme dllexport, mais j'ai essayé. Ça ne produit pas de librairie comme dans une Dll
    la déclaration de la fonction dans l'appelant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    __declspec(dllimport) std::wstring GetDirectory( std::wstring NameOfWord);
    l'appel de la fonction dans la DLL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    wsWorkDirectory = GetDirectory(  L"wsWorkDirectory");
    si je ne met pas de déclaration j'ai un message appel d'une fonction non déclarée et si je la met j'ai un unresolved external.
    comment déclarer une fonction dans une DLL qui soit fourni par l'exécutable principal.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 049
    Par défaut
    Regarde plutôt un système de CallBack pour fournir le pointeur (ou une table de pointeur) des fonctions que tu souhaites voir "exporter" par le programme

    Voir aussi aussi les ActiveX et RegisterActiveObject\GetActiveObject
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut Bonjour
    Bonjour,
    J'ai doc codé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    callback std::wstring GetDirectory( std::wstring NameOfWord);
    mais le compilateur me répond erreur de syntaxe de la déclaration
    à+

  4. #4
    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
    Le dllexport sert seulement lorsque tu crées une DLL pour dire quelles fonctions sont visibles de l'extérieur (le programme principal). Je ne connais malheureusement pas très bien l'usage de dllimport et je les utilise toujours ensemble (mais seulement au niveau de la DDL: __declspec(dllexport,dllimport)). Alors peut-être que je me trompe mais si ta fonction GetDirectory() est dans le programme principal et doit être appelé DEPUIS la DLL, alors tu n'as rien de spécial a déclarer. Il faut toutefois que tu transmette l'adresse de la fonction à la DLL à un moment ou un autre. C'est ça le système de callback.

    Pour cela il faut que la fonction de la DLL connaisse la signature de la fonction de callback qu'elle doit appeler. Voici un exemple:

    Dans la DLL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Déclaration de la signature attendue par la fonction
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
     
    // Déclaratin de la fonction appelée depuis le programme principal
    extern "C" __stdcall __declspec(dllexport,dllimport) MyDLLFunction(MyCallbackFunctionType myFunction) {
     
      if (myFunction!=NULL) {
        std::wstring result=myFunction(L"wsWorkDirectory");
      }
     
    }
    Dans ton programme principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // Déclaration de la fonction de callback (en fait une fonction "normale")
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
    ...
    }
     
    // Appel de la DLL en lui transmettant la fonction avec la bonne signature
    MyDLLFunction(&GetDirectory);

  5. #5
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut Avancons ensemble
    Bonjour,
    Votre explication m'a beaucoup servi
    cependant je n'arrive pas encore au résultat
    voila ce que j'ai fait à partir de vos explications
    Dans la Dll la déclaration:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
    std::wstring result;
    // Déclaratin de la fonction appelée depuis le programme principal
    extern  __stdcall __declspec(dllexport,dllimport) MyGetDirectory(MyCallbackFunctionType GetDirectory)
    {
      if ( GetDirectory!= NULL)
      {
        result = GetDirectory(L"wsWorkDirectory");
      }
    }
    ensuite l'appel dans le corps du programme
    J'ai d'abord testé la variable result qui est nulle
    puis j'ai codé comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MyGetDirectory(&GetDirectory);
    wsWorkDirectory = result;
    et là le compilateur me répond : symbol GetDirectory non défini
    La fonction dans le programme appelé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
    qui ne pose problème ni à la compilation, ni a l'exécution
    Je prends le parallèle avec votre exemple et je ne vois pas ou je me suis trompé?
    à+

  6. #6
    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
    Bonjour,

    Vous dites:
    Citation Envoyé par JeanNoel53 Voir le message
    ensuite l'appel dans le corps du programme
    J'ai d'abord testé la variable result qui est nulle
    C'est bizarre car votre variable "result" est en fait déclarée dans la DLL et ne devrait donc pas être accessible par le corps du programme... alors que GetDirectory() devrait être dans le corps du programme est donc accessible.

    Comme tout est inversé, pourriez-vous me donner les noms de fichiers correspondant à chaque code que vous avez posté?

    Je suis parti du principe que la fonction "GetDirectory()" se trouve dans le corps du programme et la fonction "MyDLLFunction" est dans la DLL. Par ailleurs, je constate que j'ai oublié de retourner le résultat depuis "MyDLLFunction":

    Dans la DLL:
    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
     
    // Déclaration de la signature attendue par la fonction
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
     
    // Déclaratin de la fonction appelée depuis le programme principal
    extern "C" __stdcall __declspec(dllexport,dllimport) MyDLLFunction(MyCallbackFunctionType myFunction) {
     
      static std::wstring result;
     
      result=L"";
      if (myFunction!=NULL) {
        result=myFunction(L"wsWorkDirectory");
      }
     
      return result;
     
    }
    Et le programme principal devrait retrouver le texte (j'ai mis "result" en statique pour s'assurer que l'espace mémoire de la variable n'est pas détruit au moment du retour (il faut faire bien attention à faire une COPIE de son contenu dans le programme principal car elle peut être modifiée par un nouvel appel à MyDLLFunction)

  7. #7
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut Quand déclenche t'on l'appel à la fonction callback
    Bonjour, et merci encore pour vos conseils, c'est

    J'ai un doute sur l'activation de la fonction DLL cette activation dans mon cas ne doit pas se faire avec le constructeur, car la variable n'est pas encore créer à ce moment, mais au niveau d'une initialisation de début de programme.
    Il n'y a rien de bizarre a l'inexistence de donnée sur le test fait avec un appel dans le constructeur car à ce moment là la variable n'est pas initialisée.
    mais mon besoin est d'appeler le callback à un moment précis et c'est là que j'ai la difficulté de compilation.

  8. #8
    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
    Si ton appel à la fonction de Callback ne se fait pas directement dans la fonction qui est appelée, alors tu peux faire une fonction initialisation qui détermine le callback. Tu peux enregistrer l'adresse dans une variable globale de la DLL et l'utiliser plus tard depuis une autre fonction de la DLL

  9. #9
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut il faut pouvoir récupérer l'addresse
    Bonjour, et merci encore pour ton suivi.
    quel que soit l'endroit ou je met l'instruction d'activation de la callback, comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MyGetDirectory(&GetDirectory);
    Le compilateur me jette avec le diagnostic symbole GetDirectory non défini

    J'ai mis un exemple avec le constructeur
    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
     
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
    static std::wstring result;
    // Déclaratin de la fonction appelée depuis le programme principal
    extern  __stdcall __declspec(dllexport,dllimport) MyGetDirectory(MyCallbackFunctionType GetDirectory)
    {
      if ( GetDirectory!= NULL)
      {
        result = GetDirectory(L"wsWorkDirectory");
      }
    }
     
    /*---------------------------------------------------------------*/
    /*               CLASS PARSERMANAGER                             */
    /*---------------------------------------------------------------*/
    __declspec (dllexport) CParserManager::CParserManager()
    {
    int res;
    char ReturnBuffer[1024];
    #ifdef XELDA
       _control87(MCW_EM, MCW_EM);
       m_pXeldaManager = CXeldaManager_New(LANGUAGE_NONE);
       // Opening of Xelda
       CXeldaManager_Open(m_pXeldaManager);
    #endif
       MyGetDirectory(&GetDirectory);
       wninit( ReturnBuffer, 1024);
    }
    à+

  10. #10
    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
    C'est normal puisque tu es dans la DLL et que la fonction GetDirectory n'existe pas dans la DLL!

    C'est ton programme principal qui doit fournir l'adresse de GetDirectory à la DLL puisqu'elle appartient à son scope. Dans ton exemple, ce serait comme paramètre du constructeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    __declspec (dllexport) CParserManager::CParserManager(MyCallbackFunctionType GetDirectory)
    {
    int res;
    char ReturnBuffer[1024];
    #ifdef XELDA
       _control87(MCW_EM, MCW_EM);
       m_pXeldaManager = CXeldaManager_New(LANGUAGE_NONE);
       // Opening of Xelda
       CXeldaManager_Open(m_pXeldaManager);
    #endif
       MyGetDirectory(&GetDirectory);
       wninit( ReturnBuffer, 1024);
    }

  11. #11
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut Je ne comprend pas tout et ...
    Bonjour,

    Je ne vois pas comment on modifie le programme principal pour donner l'adresse de la fonction
    et le code que tu proposes pour le constructeur n'améliore pas les choses. pourrais tu m'en dire un peu plus?

  12. #12
    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
    Ton programme principal doit bien appeler le constructeur de CParserManager à un moment à un autre. A ce moment il doit donner l'adresse de la fonction de callback comme paramètre:

    Programme principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    // La fonction de callback
    // Déclaration de la fonction de callback (en fait une fonction "normale")
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
     
    // Dans une autre fonction du programme:
    CParserManager toto(&GetDirectory);

  13. #13
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut Bonjour,
    Je trouve toujours tes conseils positif
    J'ai une implémentation qui compile et se plante à l'exécution dans la deuxième étape. Ce ne veut pas dire que la première étape est bonne. c'est peut être elle qui est en cause. J'ai déboguer en utilisant le niveau assembleur et il de plante dans le début de la constitution du masque d'appel.
    Le code de la DLL est construit comme ça:
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
     
    extern int iCount;
    extern bool bCompouned;
    extern bool bIsIdentifier;
     
    CAnalysedWord *pCurrentAnalysedWord;
    static std::wstring wsTempStringForConversion;
    static int nBloc = 0;
    extern bool bIsInRecursion;
    extern CStrConv objStrConv;
    std::wstring wsWorkDirectory;
    char* MorphParagraph( char* ReturnBuffer );
    char* strtolower( char *str);
    extern int morphinit(void);
    int wninit(char* ReturnBuffer, int MaxLen);
    char* strtolowerwithnomarker( char *str);
    extern CMorphSynset objMorphSynset;
    extern CStrToken objStrToken;
    extern char pLemma[];
    /*_____LOCAL-DATA_____________________________________________________________*/
    /*_____LOCAL-MACROS___________________________________________________________*/
    /*_____LOCAL-FUNCTIONS-PROTOTYPES_____________________________________________*/
    /*_____GLOBAL-FUNCTIONS_______________________________________________________*/
    /*_____LOCAL-FUNCTIONS________________________________________________________*/
    // extern "C" __declspec(dllimport) int __stdcall Global_getter(char *Data, int *Len, char *Test);
    //callback std::wstring GetDirectory( std::wstring NameOfWord);
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
    static std::wstring result;
    // Déclaratin de la fonction appelée depuis le programme principal
    extern  __stdcall __declspec(dllexport,dllimport) MyGetDirectory(MyCallbackFunctionType GetDirectory)
    {
      if ( GetDirectory!= NULL)
      {
        result = GetDirectory(L"wsWorkDirectory");
      }
    }
     
    /*---------------------------------------------------------------*/
    /*               CLASS PARSERMANAGER                             */
    /*---------------------------------------------------------------*/
    __declspec (dllexport) CParserManager::CParserManager()
    {
    int res;
    char ReturnBuffer[1024];
    #ifdef XELDA
       _control87(MCW_EM, MCW_EM);
       m_pXeldaManager = CXeldaManager_New(LANGUAGE_NONE);
       // Opening of Xelda
       CXeldaManager_Open(m_pXeldaManager);
    #endif
     
       //&GetDirectory(L"wsWorkDirectory");
       wninit( ReturnBuffer, 1024);
    }
     
    CParserManager* pGetDirectory;
    __declspec (dllexport) CParserManager( callBack( GetDirectory))
    {
       pGetDirectory = &callBack();
    }
     
    __declspec (dllexport) CParserManager::~CParserManager()
    {
       // CXeldaManager_Close(m_pXeldaManager);
       m_pXeldaManager = NULL;
    }
    __declspec (dllexport) erc CParserManager::InitParserManager(enLanguage Language)
    {
      erc ErrorCode = INIT_NO_ERROR;
    /*
      #ifdef XELDA
      _control87(MCW_EM, MCW_EM);
      m_pXeldaManager = CXeldaManager_New(Language);
      Opening of Xelda
      erc ErrorCode = CXeldaManager_Open(m_pXeldaManager);
    #endif
    #ifdef BRILL
    */
      CParserManager callBack( *pGetDirectory);
      //pGetDirectory(  L"wsWorkDirectory");
      wsWorkDirectory = result;
      char* s = objStrConv.awcstombs( (wchar_t*)wsWorkDirectory.c_str());
      objBrillTagger.BTagger_setup( s);
      objStrConv.StrFreeA(s);
    //#endif
      return( ErrorCode);
    }
    le compilateur est dirigé par la définition de BRILL
    et le programme principal est comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
    void* callBack(&GetDirectory);
    void *ptr = &GetDirectory;
    CParserManager                  objParserManager;
    CParserManager                  CParserManager( );
    mais la fonction qui initialise la variable n'est jamais activé
    Je serai heureux d'avoir une compréhension du phénomène et une solution à essayer. Je crains autant les problème de compilation que les problèmes d'exécution.
    à+

  14. #14
    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 JeanNoel53,

    J'ai essayé rapidement de produire un p'tit exemple complet à partir de ce que tu as fourni précédemment et de ce que Patrick a indiqué (le code fonctionne sous Builder 2010, en précisant "RTL dynamique" et Unicode dans les options de projet) .

    Par curiosité, à quoi correspond "callback" dans ton code (dans __declspec (dllexport) CParserManager( callBack( GetDirectory)) par exemple) ??

    Code de la dll (Nouveau projet, Bibliothèque de liaison dynamique, option "Générer la bibliothèque d'importation" activée), j'ai appelé le projet TestDLL :
    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
    39
    40
    41
    42
    #include <vcl.h>
    #include <windows.h>
    #pragma hdrstop
     
    #include <string>
     
    // Le type qui définit la fonction de callback
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
     
    // La fonction de callback fournie par le programme
    MyCallbackFunctionType fonctionDeCallback;
     
    typedef int erc;
    typedef int enLanguage;
     
    class CParserManager
    {
    public:
    __declspec (dllexport) CParserManager(MyCallbackFunctionType GetDirectory);
    __declspec (dllexport) erc InitParserManager(enLanguage Language);
    };
     
    __declspec (dllexport) CParserManager::CParserManager(MyCallbackFunctionType fonction)
    {
      // Mémorise la fonction de callback fournie
      fonctionDeCallback = fonction;
    }
     
    __declspec (dllexport) erc CParserManager::InitParserManager(enLanguage Language)
    {
      // Appelle la fonction de callback fournie par le programme
      std::wstring str = fonctionDeCallback(L"wsWorkDirectory");
      OutputDebugString(str.c_str());
     
      return 0;
    }
     
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
      return 1;
    }
    Code du programme de test (Nouveau projet, Application Console, VCL/C++):
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include <vcl.h>
    #pragma hdrstop
     
    #include <tchar.h>
     
    #pragma link "TestDll.lib"
     
    #include <string>
     
    // Quelques déclarations...
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
    typedef int erc;
    typedef int enLanguage;
     
    class CParserManager
    {
    public:
    __declspec (dllimport) CParserManager(MyCallbackFunctionType GetDirectory);
    __declspec (dllimport) erc InitParserManager(enLanguage Language);
    };
     
    // La chaîne qui sera envoyée à la DLL
    std::wstring wsWorkDirectory(L"Hello World");
     
    // ==> Code de Patrick
     
    // La fonction de callback
    // Déclaration de la fonction de callback (en fait une fonction "normale")
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
     
    // Dans une autre fonction du programme:
    CParserManager toto(&GetDirectory);
     
    // <== Code de Patrick
     
    #pragma argsused
    int _tmain(int argc, _TCHAR* argv[])
    {
      // Utilisation
      toto.InitParserManager(42);
     
      return 0;
    }
    Est-ce que cela correspond à ce que tu veux faire ??

  15. #15
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut On avance bien grace à vous
    Bonjour a vous

    Je vous remercie à nouveau pour vos apports
    Après intégration de vos remarques
    J'ai maintenant une application qui se génère parfaitement
    Et il faut avancer sur les problèmes d'exécution
    Je vais vous donner le code tel qu'intégré, puis mes observations sur le débogue, et je terminerai par une question.
    Le code est structurée en 4 fichiers
    L'include de la DLL (ParserManager.h)
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    #ifndef PARSERMANAGER_H
    #define PARSERMANAGER_H
    /*_____INCLUDE-FILES__________________________________________________________*/
    #include "Macro.h"
    #include "Analyse.h"
    #include "Message.h"
    #include "Lemma.h"
    #include "Event.h"
    #include "StrConv.h"
    #include "MorphSynset.hpp"
    #ifndef SCHEDULERGLOBAL_H
    #include "MMIMorphwiever.h"
    #endif
    #include "StrToken.h"
    /*_____GLOBAL-DEFINE__________________________________________________________*/
     
    #define LEMMA_TRANSLATION_NUMBER 100
    #define LEMMA_SIZE 256
    #define WORD_NUMBER_OF_A_BLOC 5000
    /*_____GLOBAL-TYPES___________________________________________________________*/
     
    /*_____GLOBAL-DATA____________________________________________________________*/
    /*_____GLOBAL-MACROS__________________________________________________________*/
    /*_____GLOBAL-FUNCTIONS-PROTOTYPES____________________________________________*/
     
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
    static std::wstring result;
    // Déclaratin de la fonction appelée depuis le programme principal
    extern  __stdcall __declspec(dllexport,dllimport) 
    {
      if ( GetDirectory!= NULL)
      {
        result = GetDirectory(L"wsWorkDirectory");
      }
    }
    // La fonction de callback fournie par le programme
    MyCallbackFunctionType fonctionDeCallback;
    /*_____CLASS-DEFINITION_______________________________________________________*/
     
    class CParserManager
    {
      public :
      __declspec (dllexport) CParserManager(MyCallbackFunctionType GetDirectory);
      __declspec (dllexport) erc InitParserManager(enLanguage Language);
      private :
        CStrConv objStrConv;
        enum enParserManager{
           PARSER_UNDEFINED = 0,
           PARSER_CPARSERMANAGER,
           NUMBER_OF_PARSER_CLASS,
        };
        enum{
          PARSE_BLOC = 1,
          GET_TRANSLATIONS_OF_SOURCE_LEMMA
        };
     
        enLanguage m_Language;
        void *m_pXeldaManager;
      public :
        CParserManager::CParserManager();
        CParserManager::~CParserManager();
     
        erc CParserManager::ParseBloc(CBloc *pBloc, std::list<CAnalysedWord *> &ListWord);
        erc CParserManager::GetTranslationsOfSourceLemma(std::wstring wsSourceLemma, enLanguage SourceLanguage,enLanguage TargetLanguage, std::list<CLemmaDescription *> &ListLemmaTranslation);
        void QualifPivot( stANALYSED_WORD * pListAnalysedWord, int ulWordNumber);
        int CParserManager::UTranscodePartOfSpeech( char* str, char* pPOS, char* pFlex);
        bool CParserManager::BSeachForFullStop( char* pWord, int* iPos);
        void CParserManager::BSplitTag( char* pNextToken, char* pWord, char* pPos, char* pFlex);
        char* CParserManager::ExtractRegularExpression( char* Buffer);
        erc CParserManager::Brill_ParseBloc(  char * InText, stANALYSED_WORD * pListAnalysedWord, unsigned long* ulWordNumber, unsigned long* ulStart);
        CParserManager::StoreAnalizedWords( stANALYSED_WORD * pListAnalysedWord, unsigned long* ulWordNumber, char* pWord, char* pNextLemma, int iPos, int* pStatus, bool bNewText, unsigned long* ulStart, int len);
        bool CParserManager::ProcessUnknownWord( char* pNextLemma, char* pWord, int lenBuffer, stANALYSED_WORD * pListAnalysedWord, unsigned long* ulWordNumber, unsigned long* ulStart);
        erc CParserManager::ParserAnalyse( stANALYSED_WORD * pListAnalysedWord, std::list<CAnalysedWord *> &ListWord, unsigned long ulWordNumber);
      };
    extern CParserManager objCParserManager;
     
    #endif /* PARSERMANAGER_H */
    Le début du fichier de la DLL, pour la partie qui va jusqu'à l'appel de la callback
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    *******************************************************************************/
    /*_____INCLUDE-FILES__________________________________________________________*/
    #include <algorithm>
    #include <list>
    #include <locale>
    #include <utility>
    #include <string.h>
    #include <System.hpp>
    #include <wstring.h>
    #include <vcl.h>
    #include <windows.h>
     
     
     
    #include "ParserManager.h"
    #ifdef BRILL
       #include "BTaggerc.h"
    #endif
    #pragma hdrstop
    /*_____LOCAL-DEFINE___________________________________________________________*/
    /*_____LOCAL-TYPES____________________________________________________________*/
    /*_____GLOBAL-DATA____________________________________________________________*/
    extern int iCount;
    extern bool bCompouned;
    extern bool bIsIdentifier;
     
    CAnalysedWord *pCurrentAnalysedWord;
    static std::wstring wsTempStringForConversion;
    static int nBloc = 0;
    extern bool bIsInRecursion;
    extern CStrConv objStrConv;
    std::wstring wsWorkDirectory;
    char* MorphParagraph( char* ReturnBuffer );
    char* strtolower( char *str);
    extern int morphinit(void);
    int wninit(char* ReturnBuffer, int MaxLen);
    char* strtolowerwithnomarker( char *str);
    extern CMorphSynset objMorphSynset;
    extern CStrToken objStrToken;
    extern char pLemma[];
    /*_____LOCAL-DATA_____________________________________________________________*/
    /*_____LOCAL-MACROS___________________________________________________________*/
    /*_____LOCAL-FUNCTIONS-PROTOTYPES_____________________________________________*/
    /*_____GLOBAL-FUNCTIONS_______________________________________________________*/
    /*_____LOCAL-FUNCTIONS________________________________________________________*/
    // extern "C" __declspec(dllimport) int __stdcall Global_getter(char *Data, int *Len, char *Test);
    //callback std::wstring GetDirectory( std::wstring NameOfWord);
    /*---------------------------------------------------------------*/
    /*               CLASS PARSERMANAGER                             */
    /*---------------------------------------------------------------*/
    __declspec (dllexport) CParserManager::CParserManager()
    {
    int res;
    char ReturnBuffer[1024];
    #ifdef XELDA
       _control87(MCW_EM, MCW_EM);
       m_pXeldaManager = CXeldaManager_New(LANGUAGE_NONE);
       // Opening of Xelda
       CXeldaManager_Open(m_pXeldaManager);
    #endif
     
       wninit( ReturnBuffer, 1024);
    }
     
    __declspec (dllexport) CParserManager::CParserManager(MyCallbackFunctionType fonction)
    {
      // Mémorise la fonction de callback fournie
      fonctionDeCallback = fonction;
    }
     
    __declspec (dllexport) CParserManager::~CParserManager()
    {
       // CXeldaManager_Close(m_pXeldaManager);
       m_pXeldaManager = NULL;
    }
     
    wchar_t ToLower(wchar_t ch)
    {
    	return (wchar_t)tolower(ch, std::locale());
    }
     
    __declspec (dllexport) erc CParserManager::InitParserManager(enLanguage Language)
    {
      erc ErrorCode = INIT_NO_ERROR;
    /*
      #ifdef XELDA
      _control87(MCW_EM, MCW_EM);
      m_pXeldaManager = CXeldaManager_New(Language);
      Opening of Xelda
      erc ErrorCode = CXeldaManager_Open(m_pXeldaManager);
    #endif
    #ifdef BRILL
    */
     
        // Appelle la fonction de callback fournie par le programme
      std::wstring str = fonctionDeCallback(L"wsWorkDirectory");
      char* s = objStrConv.awcstombs( (wchar_t*)wsWorkDirectory.c_str());
      objBrillTagger.BTagger_setup( s);
      objStrConv.StrFreeA(s);
    //#endif
      return( ErrorCode);
    }
    puis la déclaration et l'implémentaiton de la fonction appelé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
    void* callBack(&GetDirectory);
    void *ptr = &GetDirectory;
    CParserManager                  objParserManager;
    CParserManager                  CParserManager( );
    en enfin l'appel de l'initialisation du parser dans le programme principal
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    //---------------------------------------------------------------------------
    #include <SqlExpr.hpp>
    #include <vcl.h>
    #include <stdlib>
    #include <string.h>
    #include <System.hpp>
    #include <wstring>
    #include <iostream.h>
    #include <fstream.h>
    #include <list>
    #include <map>
    #include <time.h>
    #include <dos.h>
    #include "Macro.h"
    #include "Manager.h"
    #include "DataGlobalAligner.h"
    #pragma hdrstop
    //---------------------------------------------------------------------------
    USEFORM("MMIMemoriaAligner.cpp", FormMemoriaAligner);
    USEFORM("MMIOpenAlignDB.cpp", FormOpenAlignDB);
    USEFORM("MMINewAlignDB.cpp", FormNewAlignDB);
    //---------------------------------------------------------------------------
     
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
      CSoftwareManager *  pObjSoftwareManager;
      try
      {
        pObjSoftwareManager = new CSoftwareManager;
        bool bMMImode = true ;
        Application->Initialize();
        if (INIT_NO_ERROR != pObjSoftwareManager->Initialization(bMMImode))
        {
          delete pObjSoftwareManager;
          return 1;
        }
        delete pObjSoftwareManager;
        objParserManager.InitParserManager( 2);
        Application->Title = "ALIGNER";
        Application->CreateForm(__classid(TFormNewAlignDB), &FormNewAlignDB);
                     Application->Run();
      }
      catch (Exception &exception)
      {
        delete pObjSoftwareManager;
        Application->ShowException(&exception);
      }
      catch (...)
      {
        delete pObjSoftwareManager;
        try
        {
         throw Exception("");
        }
        catch (Exception &exception)
        {
          Application->ShowException(&exception);
        }
      }
      return 0;
    }
    A présent, mes observation sur le comportement:
    Le constructeur de ParserManager est appelé normalement et se déroule normalement;
    l'instruction CParserManager CParserManager( ); n'est pas exécuté;
    ultérieurement le programme s'arrête sur l'instruction std::wstring str = fonctionDeCallback(L"wsWorkDirectory"); car le terme fonctionDeCallback n'est pas initialisé. on n'est jamais passé dans la fonction MyGetDirectory(MyCallbackFunctionType GetDirectory)


    J'en viens a ma question: comment faut il déclarer la fonction d'initialisation du callback dans le fichier principal (voir 2° observation) pour que l'appel de la fonction d'initiatilsation de la callback soit fait à l'instruction CParserManager CParserManager( );

  16. #16
    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
    Le constructeur de ParserManager est appelé normalement et se déroule normalement;
    OK, c'est le constructeur par défaut qui est appelé: celui défini par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    __declspec (dllexport) CParserManager::CParserManager()
    {
    int res;
    char ReturnBuffer[1024];
    #ifdef XELDA
       _control87(MCW_EM, MCW_EM);
       m_pXeldaManager = CXeldaManager_New(LANGUAGE_NONE);
       // Opening of Xelda
       CXeldaManager_Open(m_pXeldaManager);
    #endif
     
       wninit( ReturnBuffer, 1024);
    }

    l'instruction CParserManager CParserManager( ); n'est pas exécuté;
    Le compilo ne semble pas générer de code pour cette instruction. D'ailleurs je n'arrive pas à voir ce que ce serait sensé faire ??


    ultérieurement le programme s'arrête sur l'instruction std::wstring str = fonctionDeCallback(L"wsWorkDirectory"); car le terme fonctionDeCallback n'est pas initialisé. on n'est jamais passé dans la fonction MyGetDirectory(MyCallbackFunctionType GetDirectory)
    Normal, vu qu'on n'a pas appelé le constructeur qui prend le callback en paramètre.


    J'en viens a ma question: comment faut il déclarer la fonction d'initialisation du callback dans le fichier principal (voir 2° observation) pour que l'appel de la fonction d'initiatilsation de la callback soit fait à l'instruction CParserManager CParserManager( );
    Une solution possible: redéfinir tes constructeurs pour n'en garder qu'un qui fera tout le boulot.
    Par exemple, dans le .h de la DLL, tu enlèves CParserManager::CParserManager();
    Dans le .cpp de la DLL, tu réunis les 2 constructeurs:
    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
    //__declspec (dllexport) CParserManager::CParserManager()
    //{
    //}
     
    __declspec (dllexport) CParserManager::CParserManager(MyCallbackFunctionType fonction)
    {
      // Mémorise la fonction de callback fournie
      fonctionDeCallback = fonction;
     
    int res;
    char ReturnBuffer[1024];
    #ifdef XELDA
       _control87(MCW_EM, MCW_EM);
       m_pXeldaManager = CXeldaManager_New(LANGUAGE_NONE);
       // Opening of Xelda
       CXeldaManager_Open(m_pXeldaManager);
    #endif
     
       wninit( ReturnBuffer, 1024);}
    Et dans ton programme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
    //void* callBack(&GetDirectory);
    //void *ptr = &GetDirectory;
    CParserManager                  objParserManager(&GetDirectory);
    //CParserManager                  CParserManager( );
    Autre possibilité: conserver ton constructeur par défaut, et faire de ton 2ème constructeur une fonction d'initialisation à part:
    Dans le .h de la DLL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class CParserManager
    {
      public :
     __declspec (dllexport) void InitCallback(MyCallbackFunctionType fonction);
    ...
    Dans le .cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    __declspec (dllexport) void CParserManager::InitCallback(MyCallbackFunctionType fonction)
    {
      // Mémorise la fonction de callback fournie
      fonctionDeCallback = fonction;
    }
    Et dans le programme principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
    //void* callBack(&GetDirectory);
    //void *ptr = &GetDirectory;
    CParserManager                  objParserManager;
    //CParserManager                  CParserManager( );
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
    ...
        objParserManager.InitCallback(&GetDirectory);
        objParserManager.InitParserManager( 2);

  17. #17
    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
    Superbe réponse, bravo :-)

  18. #18
    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
    Citation Envoyé par Patrick Seuret Voir le message
    Superbe réponse, bravo :-)
    Merci. Mais j'en ai sué
    J'espère qu'avec ça ça finira par marcher ce fichu callback...

  19. #19
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut Merci a ceux qui en ont sué
    Je leur souhaite un Bonjour
    Et leur conseil ont permis de résoudre tous les problèmes. Pour la postérité, je donne l'implémentation vérifiée. J'ai choisi la deuxième proposition, car mon expérience m'apprend que C++ builder tolère mal les constructeurs avec passage de paramètre
    D'abord le programme principal
    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
    39
    40
     
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
      CSoftwareManager *  pObjSoftwareManager;
      try
      {
        pObjSoftwareManager = new CSoftwareManager;
        bool bMMImode = true ;
        Application->Initialize();
        if (INIT_NO_ERROR != pObjSoftwareManager->Initialization(bMMImode))
        {
          delete pObjSoftwareManager;
          return 1;
        }
        delete pObjSoftwareManager;
        objParserManager.InitCallback( &GetDirectory);
        objParserManager.InitParserManager( enLanguage (LANGUAGE_ENGLISH));
        Application->Title = "ALIGNER";
        Application->CreateForm(__classid(TFormNewAlignDB), &FormNewAlignDB);
                     Application->Run();
      }
      catch (Exception &exception)
      {
        delete pObjSoftwareManager;
        Application->ShowException(&exception);
      }
      catch (...)
      {
        delete pObjSoftwareManager;
        try
        {
         throw Exception("");
        }
        catch (Exception &exception)
        {
          Application->ShowException(&exception);
        }
      }
      return 0;
    }
    on y appelle en séquence l'initialisation de la callback et l'initialisation du parser dans laquelle on appelle la fonction de callback et on initialise la variable qui était attendu à la bonne valeur
    Ensuite l'include du programme principal dans lequel est défini l'appel de la fonction qui renseigne la variable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    std::wstring GetDirectory( std::wstring NameOfWord)
    {
       if( wcscmp( NameOfWord.c_str(), L"wsWorkDirectory") == 0)
          return( wsWorkDirectory);
       else
          return(0);
    }
     
    CParserManager                    objParserManager;
    CPOS                              objPOS;
    CMessage                          objMessage;
    pus le code de la DLL: il y a trois fonctions le constructeur, l'initialisation de la callback et l'initialisation du programme, qui sont déclarés dans un include
    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
     
    typedef std::wstring (*MyCallbackFunctionType)(std::wstring);
    static std::wstring result;
    // Déclaratin de la fonction appelée depuis le programme principal
    extern  __stdcall __declspec(dllexport,dllimport) MyGetDirectory(MyCallbackFunctionType GetDirectory)
    {
      if ( GetDirectory!= NULL)
      {
        result = GetDirectory(L"wsWorkDirectory");
      }
    }
    // La fonction de callback fournie par le programme
    MyCallbackFunctionType fonctionDeCallback;
    /*_____CLASS-DEFINITION_______________________________________________________*/
     
    class CParserManager
    {
      public :
      __declspec (dllexport) CParserManager(MyCallbackFunctionType GetDirectory);
      __declspec (dllexport) erc InitParserManager(enLanguage Language);
      __declspec (dllexport) void InitCallback(MyCallbackFunctionType fonction);
    il y a bien sur d'autres déclarations dans cet include, mais ce qu'il faut respecter c'est d'une part ce qui est défini en dehors de la classe
    et d'autre part ce qui est défini à l'intérieur de la classe.
    dernière partie le code de la DLL: constructeur, initcallback et InitParser
    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
     
    __declspec (dllexport) CParserManager::CParserManager()
    {
    int res;
    char ReturnBuffer[1024];
       wninit( ReturnBuffer, 1024);
    }
    __declspec (dllexport) void CParserManager::InitCallback(MyCallbackFunctionType fonction)
    {
      // Mémorise la fonction de callback fournie
      fonctionDeCallback = fonction;
    }
     
    __declspec (dllexport) CParserManager::~CParserManager()
    {
       // CXeldaManager_Close(m_pXeldaManager);
       m_pXeldaManager = NULL;
    }
     
    __declspec (dllexport) erc CParserManager::InitParserManager(enLanguage Language)
    {
      erc ErrorCode = INIT_NO_ERROR;
     
      // Appelle la fonction de callback fournie par le programme
      std::wstring str = fonctionDeCallback(L"wsWorkDirectory");
      wsWorkDirectory.assign( str);
      char* s = objStrConv.awcstombs( (wchar_t*)wsWorkDirectory.c_str());
      objBrillTagger.BTagger_setup( s);
      objStrConv.StrFreeA(s);
      return( ErrorCode);
    }
    il faut simplement penser à reporter le résultat de la callback ( str ) dans la variable wsWorkDirectory, c'est le rôle de l'assign.
    merci à tous, c'était un problème un peu touchy et les réponses ont été de très haute qualité

  20. #20
    Membre extrêmement actif
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Par défaut et je remet le couvert
    Bonjour
    J'ai eu besoin d'une deuxième callback pour gérer mon développement.
    J'ai donc reproduit la structure ci dessus
    J'ai introduit dans la DLL les déclarations suivantes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    typedef erc(*MyCallbackFunctionType1)(bool, std::wstring, std::wstring, std::wstring, std::wstring*, std::wstring*);
    // La fonction de callback fournie par le programme
    MyCallbackFunctionType1 AlignFiles;
    J'ai une fonction d'init qui doit mémoriser l'adresse de la fonction à appeller comme call back
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    __declspec (dllexport) void CMenuToolbarManager::InitCallback( MyCallbackFunctionType1 fonction)
    {
      // Mémorise la fonction de callback fournie
      AlignFiles = fonction;
    }
    Jai l'appel de la fonction un peu plus loin
    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
     
     if( bIsOk == true)
        {
           /* If the encoding system of either the source or target document is empty
           and if the document is of htm, html, xml ot txt type then, get the
           default encoding system */
           if ((*psDocType == L"htm") || (*psDocType == L"html")|| (*psDocType == L"xml") || (*psDocType == L"txt"))
           {
             if ((psSourceEncode->empty()) || (psTargetEncode->empty()))
             {
               // Get the default encoding system
             }
           }
           // à passer en callback
           if (FAILURE == AlignFiles(m_bMMIMode, *psSourceFileName,
                 *psTargetFileName, *psDocType, psDbType, psDbName))
           {
             return FAILURE;
           }
           bSourceDisplayed = false;
           bTargetDisplayed = false;
        }
    et j'ai la fonction appeler en call back dans le main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    erc AlignDocumentsPairs(bool bMMIMode,
                                                   std::wstring sSourceFileName,
                                                   std::wstring sTargetFileName,
                                                   std::wstring sDocType,
                                                   std::wstring *sDatabaseType,
                                                   std::wstring *sDatabaseFileName)
    et l'initialisation des valeur dans le main
    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
    39
    40
    41
     
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
      CSoftwareManager *  pObjSoftwareManager;
      try
      {
        pObjSoftwareManager = new CSoftwareManager;
        bool bMMImode = true ;
        Application->Initialize();
        if (INIT_NO_ERROR != pObjSoftwareManager->Initialization(bMMImode))
        {
          delete pObjSoftwareManager;
          return 1;
        }
        delete pObjSoftwareManager;
        objParserManager.InitCallback( &GetDirectory);
        objMenuToolbarManager.InitCallback( &AlignDocumentsPairs);
        objParserManager.InitParserManager( 2);
        Application->Title = "ALIGNER";
        Application->CreateForm(__classid(TFormMemoriaAligner), &FormMemoriaAligner);
                     Application->Run();
      }
      catch (Exception &exception)
      {
        delete pObjSoftwareManager;
        Application->ShowException(&exception);
      }
      catch (...)
      {
        delete pObjSoftwareManager;
        try
        {
         throw Exception("");
        }
        catch (Exception &exception)
        {
          Application->ShowException(&exception);
        }
      }
      return 0;
    }
    et quand je passe dans la fonction d'initialisation de la DLL je ressort avec une adresse nulle, alors que dans l'autre appel ca se passe très bien
    Qu'y a t il de différent et que faut il faire pour que la variable AlignFiles soit affecté par la valeur de fonction?
    Il semble en fait que il faille déclarer les variables en static, ce qui introduit 2 contraintes de fait
    Les fonction qui utilisent la callback doivent être dans la même classe
    Les fonctions appelées dans la callback doivent se trouver dans la classe du main
    Je ne sais pas si ces contraintes proviennent du C++ ou de borland, mais je sais qu'il faut ça pour Borland.

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

Discussions similaires

  1. Le grand mode d'emploi du forum, à lire si vous souhaitez tout savoir !
    Par Anomaly dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 2
    Dernier message: 03/06/2013, 17h36
  2. [débutante][Concept] Destruction d'objet, mode d'emploi?
    Par skea dans le forum Général Java
    Réponses: 4
    Dernier message: 12/06/2004, 21h48

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