none
api rest c++ casablanca microsoft, sauver les champs json de la reponse dans 2 objets externes à la fonction lambda,capture list (ca plante!!!) RRS feed

  • Question

  • Bonjour,

    j'utilise l'api rest c++ casablanca dans un objet COM MTA .

    j'ai fait une requete http et je recois une reponse dont j'extraie le json et je veux sauver tous mes champs json dans deux objets externes à la fonction lambda.comme j'ai un pointeur sur  mes deux objets externes dans la classe de la methode ou j'appelle requete et reponse j'ai essayé avec [this] comme capture list et dans la focntion lambda je fait this->objet1->set et ca plante à ce moment. j'ai aussi essayé avec deux pointeurs externes à la fonction lambda et initialisés avec mes deux pointeurs membres et avec [pointeur1,pointeur2] comme capture list et ca plante quand je fait pointeur1->set et j'ai aussi essayé avec deux objets externes à la fonction lambda et avec [&objet1,&objet2] comme capture list et ca plante aussi si je fait objet1.set (set pour sauver un champ json).....

    j'utilise visual studio 2013 avec win sdk 7.1A (je suis sur  win7 sp1) et la derniere version de casablanca.



    mercredi 15 juillet 2015 13:14

Réponses

  • apparemment c'est m_offre qui a un probleme mais j'ai contourné le probleme comme je n'avais pas besoin d'allouer dynamiquement cet objet, j'ai utilise un objet MyOffre et un objet User directement comme membres de mon composant COM et maintenant ca fonctionne,je peux stocker mes valeurs avec m_offre.setid(loffre.id());

    je ne sais pas pourquoi la simple utilisation de pointeur et allocation dynamique,ne marche pas dans mon objet COM peut etre fallait il utiliser des CComPtr,je ne sais pas mais j'ai contourné le probleme.

    pour les autres problemes que j'avais avec l'api casablanca en fait j'ai vu qu il fallait faire un test si la valeur  json est null avant de l'affecter notamment pour les chaines sinon ca plante :

    if (!user[L"nom"].is_null())
                            luser.setNom(user[L"nom"].as_string().c_str());

    bon mes problemes  ont l'air d'etre resolus.....

    • Marqué comme réponse stephane_l2 jeudi 16 juillet 2015 14:12
    jeudi 16 juillet 2015 14:12
  • c'est resolu: j'ai alloué dynamiquement mon objet m_user dans FinalConstruct() avec un new User() et j'ai appele le pwc->FinalConstruct() depuis l'autre classe COM juste apres avoir fait le cocreateinstance.

    c'etait donc bien un probleme de COM.dans le FinalRelease() je delete mon pointeur.

    • Marqué comme réponse stephane_l2 lundi 20 juillet 2015 13:07
    lundi 20 juillet 2015 13:07

Toutes les réponses

  • Pouvez vous donner le  rapport de plantage : est ce une exception, et dans ce cas laquelle Le programme s'arrète t'il et avec quel code. J'espère que cette question vous permettra d'approcher la solution

    Jean Noël Martin

    jeudi 16 juillet 2015 07:02
  • je ne pense pas que celà puisse etre d'une aide quelconque vu que c'est un objet COM dans un plugin outlook donc dans une dll chargée par outlook (difficile de debugger) mais le voici: Unhandled exception at 0x66D72656 (xxxxx.dll) in OUTLOOK.EXE: 0xC0000005: Access violation writing location 0x74BCFAB4.

    jeudi 16 juillet 2015 07:31
  • apparemment celà plante lorsque je fais un set c'est à dire mets (ou sauvegarde) une de mes valeurs de champ json dans un de mes deux objets externes à la fonction lambda.
    jeudi 16 juillet 2015 07:34
  • dans le cas ou j'utilise deux objets externes(a la fonction lambda) locaux(a ma methode) voici l'erreur :"Unhandled exception at 0x04E352E9 (MSO.DLL) in OUTLOOK.EXE: 0xC0000602:  Une exception FailFast s’est produite. Les gestionnaires d’exceptions ne seront pas appelés et le processus va se terminer immédiatement."

    et là apparemment ca m'indique la ligne :

    }).wait();

    de mon code dont voici le debut:

    methode()

    {....

    MyOffre loffre;
    User  luser;
        requete.set_request_uri(u);
        
       
        client.request(requete).then([&loffre,&luser](http_response response)
        {
            
            if (web::http::status_codes::OK == response.status_code())
            {
                
                std::shared_ptr<web::json::value> jv = std::make_shared<web::json::value>(response.extract_json().get());
                
                    json::value offre = jv->at(L"offre");
                    json::value user = jv->at(L"user_json");
          

                   loffre.setId(offre[L"id"].as_integer());

                   .......

                   luser.setId((long)user[L"id"].as_double());

                   .......

    }).wait();

    m_offre->setid(loffre.id());

    .......

    m_user->setid(luser.id());

    ......

    }

    jeudi 16 juillet 2015 08:43
  • Je ne vois pas pourquoi le debugging d'un composant COM est plus compliqué que de debugging d'une Dll.

    Ça fonction de la même manière.

    "0xC0000602:  Une exception FailFast " semble assez souvent lié à des problèmes de sécurité et d'anti-virus.

    En utilisant "&" dans les paramètres de capture de la fonction lambda, vous les passez par références, donc pas de copie, ce qui pose problème sur des variables locales à libération automatique (référence invalide en sortie de méthode).

    Je ne vois pas, dans le code que vous nous donnez ni de "}).wait();" ni d'utilisation des paramètres de capture de la fonction lambda.


    Paul Bacelar, Ex - MVP VC++

    jeudi 16 juillet 2015 09:12
    Modérateur
  • normal, le }).wait(); est à la fin de mon code qui commencait par  la requete que j'ai donnée et à l'interieur du code apres la requete il ya des instructions telles que

    loffre.setId(offre[L"id"].as_integer()); (qui semble bien fonctionner) et aussi plus loin luser.setId((long)user[L"id"].as_double());

    (apparemment l'id de luser est à 0 quand ca plante ce qui n'est pas normal).

    je ne sais pas comment debugger en pas à pas mon plugin ie ma dll outlook en outre, puisque l'executable est outlook et la dll est chargée au demarrage d'outlook....

    quant à l'utilisation de ces deux variables locales loffre et luser,je comptais initialiser les 2 objets dont j'ai des pointeurs membres dans ma classe par leurs valeurs en dehors de la fonction lambda et avant la sortie de la methode, puisque celà ne fonctionne pas en utilisant des pointeurs locaux initialises avec mes pointeurs membres ou avec this...

    l'antivirus est completement desactivé.

    jeudi 16 juillet 2015 09:23
  • Pour le debugging :

    Mettez des points d'arrêt là où c'est nécessaire.

    Dans le configuration du projet, spécifiez que le programme à lancer pour le debugging est outlook.exe.

    Comme vous lancez outlook dans une session de debugging, le processus est le debuggee du débuggeur.

    Le débuggeur est prévenu du chargement de chaque Dll, il vérifie que la dll dispose d'information de debugging (dedans ou via des fichiers .pdb).

    Il vérifie que des poinst d'arrêt sont définis dans le code de la Dll. Si c'est le cas, il remplace le code machine correspondant à la ligne de code du point d'arrêt par un "int 3".

    En arrivant sur le "int 3", le débuggeur efface sa gruge et vous donne la main.


    Paul Bacelar, Ex - MVP VC++

    jeudi 16 juillet 2015 10:09
    Modérateur
  • pour le debugging merci, je vais essayer celà....
    jeudi 16 juillet 2015 10:15
  • en fait  j'ai supprimé certaines affectations et maintenant cela  va plus loin et cela plante quand je veux assigner mes valeurs de loffre et de luser , les objets locaux, aux objets pointés par les pointeur membre m_offre et m_user :

    m_offre->setId(loffre.id()); (apres le .wait()))

    jeudi 16 juillet 2015 13:13
  • Il faut déterminer, avec le débuggeur, lequel de ces objets est endommagé "m_offre" ou "loffre".

    Paul Bacelar, Ex - MVP VC++

    jeudi 16 juillet 2015 13:42
    Modérateur
  • apparemment c'est m_offre qui a un probleme mais j'ai contourné le probleme comme je n'avais pas besoin d'allouer dynamiquement cet objet, j'ai utilise un objet MyOffre et un objet User directement comme membres de mon composant COM et maintenant ca fonctionne,je peux stocker mes valeurs avec m_offre.setid(loffre.id());

    je ne sais pas pourquoi la simple utilisation de pointeur et allocation dynamique,ne marche pas dans mon objet COM peut etre fallait il utiliser des CComPtr,je ne sais pas mais j'ai contourné le probleme.

    pour les autres problemes que j'avais avec l'api casablanca en fait j'ai vu qu il fallait faire un test si la valeur  json est null avant de l'affecter notamment pour les chaines sinon ca plante :

    if (!user[L"nom"].is_null())
                            luser.setNom(user[L"nom"].as_string().c_str());

    bon mes problemes  ont l'air d'etre resolus.....

    • Marqué comme réponse stephane_l2 jeudi 16 juillet 2015 14:12
    jeudi 16 juillet 2015 14:12
  • finalement j'ai encore un probleme : ca bugge quand je fais

    m_user.setNom(luser.nom());

    ,j'ai visiblement un probleme avec les CString.

    luser.nom() contient dans mon exemple L"nom1" et ca plante dans l'affectation m_nom=nom de la fonction setNom().(ou m_nom est un CString).j'ai essayé plusieurs prototypes pour cette fonction avec

    User::setNom(CString nom)

    et User::setNom(const CString & nom)

    et ca plante dans tous les cas,bizarre....

    vendredi 17 juillet 2015 07:17
  • il aurait peut etre fallu que j'utilise CAtlString au lieu de CString vu que c'est un projet ATL ?
    vendredi 17 juillet 2015 07:32
  • Non CAtlString et CString, c'est la même chose et quitte à utiliser des string, autant utiliser les std::string ou les std::wstring qui font partie de la norme C++.

    Avez-vous vérifié que this est valide ? que m_user est valide ?

    C'est quoi comme type de plantage  ???


    Paul Bacelar, Ex - MVP VC++

    vendredi 17 juillet 2015 09:38
    Modérateur
  • this et m_user doivent etre valides (d'ailleurs j'affichait le m_user.id et idclient avant deux entiers longs) le plantage est :Unhandled exception at 0x04D152E9 (MSO.DLL) in OUTLOOK.EXE: 0xC0000602:  Une exception FailFast s’est produite. Les gestionnaires d’exceptions ne seront pas appelés et le processus va se terminer immédiatement. ca plante dans m_user.setNom(luser.nom());  en detail :

    void User::setNom( CString  nom)
    {
        m_nom = nom;
    }

     juste apres l'affectation et m_nom n'est pas lisible (ca affiche dans le debugger errors reading characters of string pour m_nom).

    mon ancienne version avait comme prototype

    void User::setNom( const CString & nom)
    {
        m_nom = nom;
    }

    et ca plantait aussi.

    nom() renvoie un CString:   CString   nom() const;

    vendredi 17 juillet 2015 12:37
  • en fait je cree l'objet COM dans lequel se trouve la methode ou je fais la requete http et la reponse, dans le onconnection d'un premier objet COM avec cocreateinstance et le parametre CLSCTX_INPROC_SERVER

    ensuite j'appelle cette methode plus tard dans une autre methode du premier objet COM avec

    CComPtr<Cobjet2Comm> pwc;

                
               
                if (m_pWComm->QueryInterface(IID_Iobjet2Comm, (void**)&pwc) == S_OK)
                {
                    pwc->methode()

                }

    ou Cobjet2Comm est la classe du deuxieme objet COM et methode() est ma methode ou j'utilise l'api rest et je fais une requete et reponse http, et enfin m_pWComm est de type: Iobjet2Comm *m_pWComm;

    peut etre aurait il fallu faire le cocreateinstance plus tard que dans le onconnection ? (peut etre que l'objet est mal construit ? )


    vendredi 17 juillet 2015 12:51
  • non en fait celà ne vient pas du cocreateinstance(j'ai essayé de le mettre dans le handler de l'event startup donc plus tard et j'ai toujours la meme erreur) et donc je ne voie pourquoi j'ai cette erreur sur les affectations de CString....
    vendredi 17 juillet 2015 14:11
  • Il faut localiser le problème avant de chercher son origine.

    Votre argumentaire sur la validité des objets utilisées est très lapidaire, moi je vérifierais bien plus sérieusement.

    Le fait que le débuggeur vous affiche des machins dans la fenêtre d'espion, ça prouve pas grand chose.

    >ca affiche dans le debugger errors reading characters of string pour m_nom

    Si vous êtes en debug, ça prouve que votre objet est invalide.


    Pour moi, votre objet User est invalide.

    Prouvez-moi qu'il ne l'ai pas.


    Paul Bacelar, Ex - MVP VC++

    vendredi 17 juillet 2015 14:41
    Modérateur
  • mais pourquoi serait il invalide ? c'est une variable membre de mon objet COM MTA donc elle doit etre construite à la construction de l'objet COM (dans le cocreateinstance,donc bien avant que j'appelle cette methode)

    User m_user; (declaration dans le header de l'objet COM et sinon la classe User :

    class User{

    public:
        User();
        User(const User &);
        User & operator=(const User &);

    ~User();
     ....

     CString   nom() const;
        void setNom( CString  nom);
     CString  email() const;
        void setEmail( CString  email);

         CString  password() const;
        void setPassword( CString  password);

    .....

    private:

     long m_id;

    ....

     CString m_nom;

        CString m_email;
        CString m_password;

    ......

    }

    la classe User n'est pas un composant COM mais une classe non COM dont une instance est membre de mon objet COM MTA.

    apres je ne voie pas pourquoi elle serait invalide si je l'appelle apres la creation de l'objet COM (apres le cocreateinstance), ou alors c'est que le pointeur pwc avec lequel j'appelle la methode est invalide ce que je n'ai pas verifié en fait.je le recupere peut etre mal car je fais un queryinterface pour le recuperer (cf plus haut)

    vendredi 17 juillet 2015 15:41
  • >mais pourquoi serait il invalide ?

    Loi de Murphy, suffit que l'objet soit désalloué, ou qu'un autre bug est foutu en l'aire l'objet, etc...

    C'est un réflexe à avoir, il est invalide, jusqu'à preuve du contraire. Vous cherchez des explications mais on sait toujours pas qu'est-ce qui plante, en terme plus précis que la ligne d'affectation.

    La ligne d'affectation utilise une ribambelle de choses (opérateur ->, opérateur d'affectation, accès à des membres, etc...), chacun pouvant être le lié du crash.

    Il faut savoir où ça déconne de manière bien plus précise, quitte à passer par toutes les méthodes en mode pas à pas et à voir le code assembleur pour les choses inlinées.

    "m_user.setNom(luser.nom());" c'est un énorme machin et il faut valider chaque étape, une par une.


    Paul Bacelar, Ex - MVP VC++

    vendredi 17 juillet 2015 17:18
    Modérateur
  • en tout j'affecte dans m_user.id et idclient qui sont des longs auparavant et je les affiche dans une boite de dialogue donc m_user n'est pas forcément invalide et je pencherais plutot pour un probleme avec les CString puisque je n'ai le probleme que pour les CString et je me demande d'ailleurs ce qu il faut mettre comme librairie dans le projet pour avoir notamment les CString de l'atl.....
    vendredi 17 juillet 2015 21:01
  • de plus j'utilise le win sdk 7.1A avec msvc 2013 ce qui n'est pas forcement recommandé mais parce que je suis sous windows 7 (normalement msvc 2013 est par defaut avec le win sdk 8.1)
    vendredi 17 juillet 2015 21:03
  • Utilisez le débuggeur pour en avoir le cœur net.

    CString est la classe historique des MFC pour les chaines de caractère.

    elle a été migrée vers ATL.

    Elle ne présente plus beaucoup d'avantage par rapport à la std::string du standard C++/STL.


    Paul Bacelar, Ex - MVP VC++

    dimanche 19 juillet 2015 02:34
    Modérateur
  • meme si je fais

    CString lc=luser.nom();
    m_user.setNom(lc);

    j'ai la meme erreur lors de l'affectation dans setNom alors que  lc contient bien ma chaine.

    en fait toutes les CString de m_user sont à NULL ou à error reading characters alors que les longs de m_user sont corrects

    or le m_user je fait juste avant une affectation des deux longs sinon je ne m'en sers pas.et c'est une variable membre de mon objet COM.donc le seul truc que je voie c'est que le pointeur que j'obtient par queryinterface de mon objet COM ne serait pas valide ou alors que le cocreateinstance fonctionne mal.je pourrais eventuellement faire deriver User de Cobject pour voir si celà marche mieux, mais cela impliquerait que j'inclue les mfc dans mon projet,et donc allourdirait la chose. le cocreateinstance n'appelle t'il pas le constructeur de l'objet COM?


    lundi 20 juillet 2015 09:02
  • en fait celà doit venir qu on objet COM n'est pas initialisé lors de sa creation par cocreateinstance donc il ne doit pas appeler tous les constructeurs des objets membres, donc je vais essayer d'allouer dynamiquement mes deux objets membres m_user et m_offre peut etre dans le finalconstruct et voir ce que celà donne....
    lundi 20 juillet 2015 12:26
  • c'est resolu: j'ai alloué dynamiquement mon objet m_user dans FinalConstruct() avec un new User() et j'ai appele le pwc->FinalConstruct() depuis l'autre classe COM juste apres avoir fait le cocreateinstance.

    c'etait donc bien un probleme de COM.dans le FinalRelease() je delete mon pointeur.

    • Marqué comme réponse stephane_l2 lundi 20 juillet 2015 13:07
    lundi 20 juillet 2015 13:07