{"id":201,"date":"2008-02-02T16:09:29","date_gmt":"2008-02-02T15:09:29","guid":{"rendered":"http:\/\/blog.m-ri.de\/index.php\/2008\/02\/02\/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann\/"},"modified":"2008-02-29T20:19:25","modified_gmt":"2008-02-29T19:19:25","slug":"wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2008\/02\/02\/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann\/","title":{"rendered":"Wie man sich mit CComDispatchDriver bzw. CComPtr&lt;IDispatch&gt;::InvokeN hereinlegen kann"},"content":{"rendered":"<p>Eigentlich m\u00fcsste dieser Artikel eine weitere \u00dcberschrift bekommen:<br \/>\n<strong>Wie fatal es ist, dass es keine vollst\u00e4ndige ATL Dokumentation gibt!<\/strong><\/p>\n<p>Einige werden <em>CComDispatchDriver <\/em>kennen. Seit den VS-200x Versionen ist diese Klasse nichts anderes als sie Spezialisierung <em>CComPtr&lt;IDispatch&gt;<\/em><\/p>\n<p>Ich hatte vor, eine bestimmte .NET Komponente per <em>late binding <\/em>in ein C++ Programm zu integrieren.<br \/>\nKein Problem. <em>CreateInstance<\/em>, hier ein <em>Invoke0<\/em>, dort ein <em>Invoke2 <\/em>und da noch ein <em>InvokeN <\/em>\ud83d\ude2e &#8230; und hier geht auf einmal nichts mehr. Dokumentation in der MSDN: Fehlanzeige!<\/p>\n<p>Bestandsaufnahme: Ich habe einen CComVariant Array aufgebaut und die entsprechenden Daten \u00fcbergeben. Sieht alles richtig aus. Aber ich erhalte immer nur Fehler (immer <em>E_NOINTERFACE<\/em>).<\/p>\n<ol>\n<li>OK, n\u00e4chster Schritt. Das ganze mal direkt mit dem entsprechenden Interface versuchen. Also <em>CComQIPtr<\/em> eingebaut und direkter Aufruf \u00fcber die existierende duale Schnittstelle. Komisch, nun geht es.<\/li>\n<li>Nun denn. Das ganze nun mal als Klasse mit dem Classview importiert und einen MFC Wrapper gebaut. Der verwendet ja auch <em>IDispatch. <\/em>Jetzt wird es mysteri\u00f6s: Es geht auch!<\/li>\n<\/ol>\n<p>Dann debuggen wir mal den MFC Wrapper. Schrittweise gehe ich durch den Code im <em>COleDispatchDriver::InvokeHelperV <\/em>bis Zeile 223 und dort lese ich den folgenden Code und Kommentar:<\/p>\n<pre lang=\"cpp\">pArg += dispparams.cArgs - 1; \/\/ params go in opposite order<\/pre>\n<p>\u2757 Aha! Hier liegt der Hase im Pfeffer. Ich hatte den <em>CComVariant <\/em>Array nat\u00fcrlich so aufgebaut, dass das erste Argument auch das erste Element im Array war. <em>InvokeN <\/em>will aber die selbe Reihenfolge wie <em>IDispatch::Invoke<\/em>, d.h. in umgekehrter Folge. Also beginnt der Array nun mit dem letzten Argument und endet mit dem ersten und siehe da: Es geht \u2757<\/p>\n<p>Schade, dass hier die ATL-Doku so l\u00fcckenhaft ist. Das h\u00e4tte mir hier, 2 Stunden Arbeit gespart.<br \/>\nIch h\u00e4tte es auch schneller haben k\u00f6nnen, wenn ich mir aufmerksam die Implementierung von <em>CComPtr&lt;IDispatch&gt;::Invoke2<\/em> angesehen h\u00e4tte (Man achte auf den Array varArgs):<\/p>\n<pre line=\"1\" lang=\"cpp\">inline HRESULT CComPtr&lt;IDispatch&gt;::Invoke2(__in DISPID dispid, \r\n       __in VARIANT* pvarParam1, \r\n       __in VARIANT* pvarParam2, \r\n       __out_opt VARIANT* pvarRet) throw() \r\n{ \r\n\u00a0if(pvarParam1 == NULL || pvarParam2 == NULL) \r\n\u00a0 \u00a0return E_INVALIDARG; \r\n\u00a0CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 }; \r\n DISPPARAMS dispparams = { &amp;varArgs[0], NULL, 2, 0}; \r\n\u00a0return p-&gt;Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, \r\n     DISPATCH_METHOD, &amp;dispparams, pvarRet, NULL, NULL); \r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Eigentlich m\u00fcsste dieser Artikel eine weitere \u00dcberschrift bekommen: Wie fatal es ist, dass es keine vollst\u00e4ndige ATL Dokumentation gibt! Einige werden CComDispatchDriver kennen. Seit den VS-200x Versionen ist diese Klasse nichts anderes als sie Spezialisierung CComPtr&lt;IDispatch&gt; Ich hatte vor, eine bestimmte .NET Komponente per late binding in ein C++ Programm zu integrieren. Kein Problem. CreateInstance, &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2008\/02\/02\/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eWie man sich mit CComDispatchDriver bzw. CComPtr&lt;IDispatch&gt;::InvokeN hereinlegen kann\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25,30,3],"tags":[366,92],"class_list":["post-201","post","type-post","status-publish","format-standard","hentry","category-atl","category-c","category-programmieren","tag-atl","tag-com"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=201"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/201\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=201"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}