<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[COM Klasse (attributed C++), Events, injected Code]]></title><description><![CDATA[<p>Ich hab' hier nen COM Server der mit MSVC8 (SP1) und attributed C++ implementiert ist. Da drinnen gibts dann Klassen die eben Events schicken können, so mit __event - geht ja alles erstmal schön. Sämtliche Klassen sind mit threading(&quot;free&quot;) markiert.<br />
Und nu sind wir beim Fehler Suchen über was drübergestolpert... nämlich die Implementierung der injizierten Advise/Unadvise Funktionen sowie der &quot;schicke Event X raus&quot; Funktionen. Und diese sehen für meine Augen ziemlich fischig aus.</p>
<p>Schematisch sieht das so aus:</p>
<pre><code class="language-cpp">HRESULT MyClass::EventBlubb()
{
   // ...
   Lock();
   IUnknown** pp = this-&gt;m_vec.begin();
   Unlock();
   for(; pp != this-&gt;m_vec.end(); pp++)
   {
      __WeissNimmerWasGenau(*pp, ...);
   }
   // ...
}
</code></pre>
<p>Und ich denke dieser Code ist oberfaul.</p>
<p>In der Funktion wird weder eine lokale Kopie der Daten in m_vec gemacht, noch wird der Lock lange genug aufrecht erhalten (was dann aus anderen Gründen wieder problematisch wäre) -- ruft jmd. in der Zeit wo EventBlubb() läuft also Advise oder Unadvise auf, dann krachts u.U.<br />
(Advise bzw. Unadvise können zum Beispiel dazu führen dass der von m_vec.begin() bzw. m_vec.end() zurückgelieferte Pointer sich ändert, bzw. auch einfach der Inhalt des Vectors).<br />
Und BTW: m_vec ist KEIN std::vector sondern irgendsoein ATL Zeugs, ist aber in dem Fall ziemlich egal, m_vec kümmert sich auch NICHT um irgendwelche Synchronisierungsgeschichten. Könnte es auch garnicht, nicht wenn der Code aussen so aussieht wie er nunmal aussieht.</p>
<p>Ist jmd. von euch schonmal über dieses Problem drübergestolpert? Falls es jmd. interessiert der es noch nicht weiss: den injizierten Code kann man sich z.B. ansehen indem man in den Project-Settings unter &quot;Output Files&quot; die Option /Fx einstellt (&quot;Expand Attributed Source: yes&quot;). Oder indem man mit dem Debugger einfach reinsteppt...</p>
<p>Und wichtiger: weiss jmd. eine Lösung?<br />
Speziell auch für folgenden Fall:</p>
<ol>
<li>Client ruft Advise() auf</li>
<li>COM Server fängt an einen Event an alle registrierten Clients zu schicken, holt sich grad den Zeiger auf unseren Client und ...</li>
<li>Client ruft Unadvise auf (und Unadvise gibt die Sink-Referenz frei!)</li>
<li>Client zerstört seine Sink (&quot;der Sink&quot;/&quot;die Sink&quot; ... ? egal.)</li>
<li>COM Server läuft weiter wo er bei 2) stehengeblieben ist, und schickt den Event an den alten Interface Zeiger aus -- die Referenz wurde aber bereits hergegeben, und das Objekt ist schon tot. Pöse <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></li>
</ol>
<p>Klar könnte ich die Implementierung von Advise(), Unadvise() und EventXYZ() selbst schreiben so dass das passt, aber irgendwo hatte ich ja doch gehofft dass dieses &quot;attributed C++ COM Zeugs&quot; mir genau sowas abnehmen würde... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>p.S.: MSVC7.1 (SP1) generiert bis auf ein kleines (und in dem Fall unwichtiges) Detail genau den selben Code.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/176971/com-klasse-attributed-c-events-injected-code</link><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Apr 2026 22:04:59 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/176971.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 26 Mar 2007 20:10:32 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Mon, 26 Mar 2007 20:10:32 GMT]]></title><description><![CDATA[<p>Ich hab' hier nen COM Server der mit MSVC8 (SP1) und attributed C++ implementiert ist. Da drinnen gibts dann Klassen die eben Events schicken können, so mit __event - geht ja alles erstmal schön. Sämtliche Klassen sind mit threading(&quot;free&quot;) markiert.<br />
Und nu sind wir beim Fehler Suchen über was drübergestolpert... nämlich die Implementierung der injizierten Advise/Unadvise Funktionen sowie der &quot;schicke Event X raus&quot; Funktionen. Und diese sehen für meine Augen ziemlich fischig aus.</p>
<p>Schematisch sieht das so aus:</p>
<pre><code class="language-cpp">HRESULT MyClass::EventBlubb()
{
   // ...
   Lock();
   IUnknown** pp = this-&gt;m_vec.begin();
   Unlock();
   for(; pp != this-&gt;m_vec.end(); pp++)
   {
      __WeissNimmerWasGenau(*pp, ...);
   }
   // ...
}
</code></pre>
<p>Und ich denke dieser Code ist oberfaul.</p>
<p>In der Funktion wird weder eine lokale Kopie der Daten in m_vec gemacht, noch wird der Lock lange genug aufrecht erhalten (was dann aus anderen Gründen wieder problematisch wäre) -- ruft jmd. in der Zeit wo EventBlubb() läuft also Advise oder Unadvise auf, dann krachts u.U.<br />
(Advise bzw. Unadvise können zum Beispiel dazu führen dass der von m_vec.begin() bzw. m_vec.end() zurückgelieferte Pointer sich ändert, bzw. auch einfach der Inhalt des Vectors).<br />
Und BTW: m_vec ist KEIN std::vector sondern irgendsoein ATL Zeugs, ist aber in dem Fall ziemlich egal, m_vec kümmert sich auch NICHT um irgendwelche Synchronisierungsgeschichten. Könnte es auch garnicht, nicht wenn der Code aussen so aussieht wie er nunmal aussieht.</p>
<p>Ist jmd. von euch schonmal über dieses Problem drübergestolpert? Falls es jmd. interessiert der es noch nicht weiss: den injizierten Code kann man sich z.B. ansehen indem man in den Project-Settings unter &quot;Output Files&quot; die Option /Fx einstellt (&quot;Expand Attributed Source: yes&quot;). Oder indem man mit dem Debugger einfach reinsteppt...</p>
<p>Und wichtiger: weiss jmd. eine Lösung?<br />
Speziell auch für folgenden Fall:</p>
<ol>
<li>Client ruft Advise() auf</li>
<li>COM Server fängt an einen Event an alle registrierten Clients zu schicken, holt sich grad den Zeiger auf unseren Client und ...</li>
<li>Client ruft Unadvise auf (und Unadvise gibt die Sink-Referenz frei!)</li>
<li>Client zerstört seine Sink (&quot;der Sink&quot;/&quot;die Sink&quot; ... ? egal.)</li>
<li>COM Server läuft weiter wo er bei 2) stehengeblieben ist, und schickt den Event an den alten Interface Zeiger aus -- die Referenz wurde aber bereits hergegeben, und das Objekt ist schon tot. Pöse <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></li>
</ol>
<p>Klar könnte ich die Implementierung von Advise(), Unadvise() und EventXYZ() selbst schreiben so dass das passt, aber irgendwo hatte ich ja doch gehofft dass dieses &quot;attributed C++ COM Zeugs&quot; mir genau sowas abnehmen würde... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>p.S.: MSVC7.1 (SP1) generiert bis auf ein kleines (und in dem Fall unwichtiges) Detail genau den selben Code.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1253358</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1253358</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 26 Mar 2007 20:10:32 GMT</pubDate></item><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Tue, 27 Mar 2007 08:43:12 GMT]]></title><description><![CDATA[<p>Bist Du sicher das dieser Code injeziert wird:</p>
<pre><code class="language-cpp">IUnknown** pp = this-&gt;m_vec.begin();
</code></pre>
<p>Und kein CComPtr? Würde mich wundern.</p>
<p>Hast Du ein sample? Muss nicht Multithreaded sen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1253605</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1253605</guid><dc:creator><![CDATA[Martin Richter]]></dc:creator><pubDate>Tue, 27 Mar 2007 08:43:12 GMT</pubDate></item><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Tue, 27 Mar 2007 09:33:52 GMT]]></title><description><![CDATA[<p>OT: Ist Attributed ATL nicht &quot;deprecated&quot;?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1253649</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1253649</guid><dc:creator><![CDATA[Jochen Kalmbach]]></dc:creator><pubDate>Tue, 27 Mar 2007 09:33:52 GMT</pubDate></item><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Tue, 27 Mar 2007 09:43:10 GMT]]></title><description><![CDATA[<p>Jupp! Ist es!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1253654</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1253654</guid><dc:creator><![CDATA[Martin Richter]]></dc:creator><pubDate>Tue, 27 Mar 2007 09:43:10 GMT</pubDate></item><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Tue, 27 Mar 2007 09:47:50 GMT]]></title><description><![CDATA[<p>Ich war zu schnell. Also für VS2005 gilt das nicht. IMHO wird es keine Fortführung in Orcas geben. Aber wie weit die das zuammenstreichen.<br />
Aber offizielles habe ich gerade nicht gefunden.</p>
<p>Atributed ATL war zum großen Teil zwischen VS2003 und VS2005 nicht komaptibel und es gibt mit dem Zeug Scherereien ohne Ende.</p>
<p>Ich ärgere mich heute noch, dass ich einen Teil der DB Features verwendet habe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1253657</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1253657</guid><dc:creator><![CDATA[Martin Richter]]></dc:creator><pubDate>Tue, 27 Mar 2007 09:47:50 GMT</pubDate></item><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Tue, 27 Mar 2007 16:50:29 GMT]]></title><description><![CDATA[<p>Was meint ihr attributed ATL ist tot/deprecated/blah *fürcht*? Heisst das ich kann mir meinen ganzen attributed-COM-Zeugs Code in die Haare schmieren wenn ich z.B. auf's neue Studio umsteigen will? Hmpf. Was gibts denn für Alternativen? Ich meine ich würde es schon hinbekommen das alles &quot;zu Fuss&quot; mit ATL auszuprogrammieren, aber es ist halt schon etwas lästig, gelinde gesagt. Der ganze doofe Glue-Code...</p>
<p>Oder gibt's vielleicht eine einfachere Möglichkeit als ATL? Irgendwas was mir hilft out-of-process COM Server (bzw. evtl. auch mal in-process) mit schönen dualen Interfaces und Events etc. in C++ zu programmieren...</p>
<p>Managed C++ möchte ich eigentlich nicht verwenden, und C++ sollte es auf jeden Fall bleiben (aus verschiedenen Gründen).</p>
<p>----</p>
<p>Hier das gewünschte Beispiel, das ist der Code den MSVC8 (SP1) erzeugt damit ich meine Events verschicken kann:</p>
<pre><code class="language-cpp">// in MyClass.h (bzw. MyClass.mrg.h) innerhalb von MyClass:

    HRESULT MyEvent(::LONG i1,::LONG i2,::LONG i3,::LONG i4) 
    {
        HRESULT hrRet = S_OK;
        HRESULT hr = S_OK;
        IConnectionPointImpl&lt;MyClass, &amp;__uuidof(MyNamespace::DMyDualInterface), CComDynamicUnkArray&gt;* p = this;
        VARIANT rgvars[4];
        Lock();
        IUnknown** pp = NULL;
        __try 
        {
            pp = p-&gt;m_vec.begin();
        }
        __finally 
        {
            Unlock();
        }
        while (pp &lt; p-&gt;m_vec.end()) {
            if (*pp != NULL) {
                IDispatch* pDispatch = (IDispatch*) *pp;
                ::VariantInit(&amp;rgvars[3]);
                rgvars[3].vt = VT_I4;
                V_I4(&amp;rgvars[3])= i1;
                ::VariantInit(&amp;rgvars[2]);
                rgvars[2].vt = VT_I4;
                V_I4(&amp;rgvars[2])= i2;
                ::VariantInit(&amp;rgvars[1]);
                rgvars[1].vt = VT_I4;
                V_I4(&amp;rgvars[1])= i3;
                ::VariantInit(&amp;rgvars[0]);
                rgvars[0].vt = VT_I4;
                V_I4(&amp;rgvars[0])= i4;
                DISPPARAMS disp = { rgvars, NULL, 4, 0 };
                VARIANT ret_val;
                hr = __ComInvokeEventHandler(pDispatch, 151, 1, &amp;disp, &amp;ret_val);
                if (FAILED(hr)) {
                    hrRet = hr;
                }
            }
            pp++;
        }
        return hrRet;
    }
</code></pre>
<p>m_vec ist dabei vom Typ CComDynamicUnkArray, und die Advise und Unadvise Funktionen können wie gesagt dazu führen dass die Pointer die .begin() bzw. .end() zurückliefern sich ändern. Der Zugriff auf m_vec innerhalb der Schleife (ohne Lock) ist IMHO also komplett falsch und ziemlich riskant.</p>
<p>MSVC 7.1 lässt das __try und __finally weg, ansonsten ist der Code gleich was ich gesehen habe. Ich hab' zwar kein diff drüber gemacht, aber die Teile um die es mir geht sind gleich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1254032</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1254032</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 27 Mar 2007 16:50:29 GMT</pubDate></item><item><title><![CDATA[Reply to COM Klasse (attributed C++), Events, injected Code on Fri, 30 Mar 2007 00:15:55 GMT]]></title><description><![CDATA[<p>Hülfe <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /><br />
Wäre froh wenn mir jmd. nen Tip geben könnte bezüglich &quot;wie macht man am einfachsten COM Server mit C++&quot;...<br />
EDIT: also anders gesagt: ist die ATL da wirklich das beste was man bekommen kann, oder gibts da noch andere gute Optionen? Ich kenne halt sonst nix...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1255692</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1255692</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Fri, 30 Mar 2007 00:15:55 GMT</pubDate></item></channel></rss>