<?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[Callback aus einer DLL]]></title><description><![CDATA[<p>Hi,</p>
<p>Ich habe einen Errorhandler, der einfach einen Eintrag in eine Datei schreibt (natürlich macht er wesentlich mehr, aber das ist für das Problem nicht wichtig). Dieser ist so angelegt, daß ich eine globale Instanz davon anlege und den Klassen, die einen Error ausgeben sollen, einfach einen Pointer auf diese Instanz gebe, womit sie die entsprechende Funktion selber aufrufen. Soweit sogut.<br />
Nun will ich eine der Klassen in eine DLL auslagern. Das Problem ist aber: Wie konstruiere ich die Aufrufe an den Errorhandler, den die DLL gar nicht kennen kann bzw nicht kennen soll. Den Errorhandler in die DLL hinein zu compilieren, ist das ganz und gar nicht Sinn der Sache.<br />
Meine Idee war nun, das mit einem Callback zu machen, das gelingt mir aber nichtmal soweit, um es zum compilieren zu bringen. Wie müßte das aussehen?</p>
<p>Die bisherige Konstruktion sieht zB so aus (ohne DLL):</p>
<pre><code class="language-cpp">class CErrorHandler {
...
    void GenerateError(int i_ErrID, std::string str_ErrText);
...
};

class CTest
{
...
    CTest(CErrorHandler *pErrHdl=NULL) { pIntErrHdl = pErrHdl; };
    void TestFunction() {
        ...
        if(pIntErrHdl)
        {
            pErr-&gt;GenerateError(12, &quot;File Access Error&quot;);
        }
        ...
    };
...
};

CErrorHanlder mErrhdl;
CTest mTest(&amp;mErrHdl);
mTest.TestFunction();
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/215953/callback-aus-einer-dll</link><generator>RSS for Node</generator><lastBuildDate>Sun, 11 Oct 2026 19:18:19 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/215953.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 17 Jun 2008 12:32:54 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Callback aus einer DLL on Tue, 17 Jun 2008 12:32:54 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>Ich habe einen Errorhandler, der einfach einen Eintrag in eine Datei schreibt (natürlich macht er wesentlich mehr, aber das ist für das Problem nicht wichtig). Dieser ist so angelegt, daß ich eine globale Instanz davon anlege und den Klassen, die einen Error ausgeben sollen, einfach einen Pointer auf diese Instanz gebe, womit sie die entsprechende Funktion selber aufrufen. Soweit sogut.<br />
Nun will ich eine der Klassen in eine DLL auslagern. Das Problem ist aber: Wie konstruiere ich die Aufrufe an den Errorhandler, den die DLL gar nicht kennen kann bzw nicht kennen soll. Den Errorhandler in die DLL hinein zu compilieren, ist das ganz und gar nicht Sinn der Sache.<br />
Meine Idee war nun, das mit einem Callback zu machen, das gelingt mir aber nichtmal soweit, um es zum compilieren zu bringen. Wie müßte das aussehen?</p>
<p>Die bisherige Konstruktion sieht zB so aus (ohne DLL):</p>
<pre><code class="language-cpp">class CErrorHandler {
...
    void GenerateError(int i_ErrID, std::string str_ErrText);
...
};

class CTest
{
...
    CTest(CErrorHandler *pErrHdl=NULL) { pIntErrHdl = pErrHdl; };
    void TestFunction() {
        ...
        if(pIntErrHdl)
        {
            pErr-&gt;GenerateError(12, &quot;File Access Error&quot;);
        }
        ...
    };
...
};

CErrorHanlder mErrhdl;
CTest mTest(&amp;mErrHdl);
mTest.TestFunction();
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1530822</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1530822</guid><dc:creator><![CDATA[HydroNom]]></dc:creator><pubDate>Tue, 17 Jun 2008 12:32:54 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Wed, 18 Jun 2008 10:33:43 GMT]]></title><description><![CDATA[<blockquote>
<p>Wie konstruiere ich die Aufrufe an den Errorhandler, den die DLL gar nicht kennen kann bzw nicht kennen soll.</p>
</blockquote>
<p>Den ersten Teil des Satzes verstehe ich nicht. Ist das Problem den Error Handler in der DLL zu nutzen oder ihn an die DLL zu uebergeben?</p>
<p>Fuer letzteres einfach eine Funktion SetErrorHandler in der DLL einfuheren, die den Error Handler an die DLL uebergibt.</p>
<p>Fuer ersteres sehe ich zwei Moeglichkeiten (wenn er nicht in der DLL einkompiliert werden soll):</p>
<ol>
<li>Error Handler inline im Header definieren</li>
<li>Polymorphie: (abstrakte) Basisklasse fuer den Error Handler und der eigentliche Error Handler ist dann nur eine Instanz einer abgeleiteten Klasse.</li>
</ol>
<p>in allen Faellen muss auf jeden Fall natuerlich der Header (im zweiten Fall der der Basisklasse) in der DLL bekannt sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1531408</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1531408</guid><dc:creator><![CDATA[DeSoVoDaMu]]></dc:creator><pubDate>Wed, 18 Jun 2008 10:33:43 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Wed, 18 Jun 2008 11:33:24 GMT]]></title><description><![CDATA[<p>Das übergeben ist nicht das Problem, ich hab an die Klasse in der DLL schon einen void-Pointer auf die entsprechende ErrorHandler-Instanz im Konstruktor mitgegeben.<br />
Wenn ich jetzt aber den errorhandler.h in die DLL einbaue, dann kann ich zwar compilieren, aber nicht linken (verständlicherweise weil der Code ja fehlt).<br />
Das Problem ist nun, wie kann ich mithilfe dieses void Pointer zB die GenerateError Funktion nutzen, ohne den ErrorHandler Code mit zu compilieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1531468</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1531468</guid><dc:creator><![CDATA[HydroNom]]></dc:creator><pubDate>Wed, 18 Jun 2008 11:33:24 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Thu, 19 Jun 2008 07:39:44 GMT]]></title><description><![CDATA[<p>Zeig doch bitte mal ein bisschen (relevanten) Code und die Fehlermeldung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1532010</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1532010</guid><dc:creator><![CDATA[DeSoVoDaMu]]></dc:creator><pubDate>Thu, 19 Jun 2008 07:39:44 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Thu, 19 Jun 2008 10:47:37 GMT]]></title><description><![CDATA[<p>Der (relevante) Code steht oben. Mehr is tatsächlich nicht, lediglich die CTest Klasse befindet sich nicht mehr im lokalen Code sondern soll in einer DLL. Dort drin hab ich im Konstruktor eben ein</p>
<pre><code class="language-cpp">CTest((void*) pErrHdl);
</code></pre>
<p>und rufe die Funktion mit</p>
<pre><code class="language-cpp">CTest myTest(&amp;mErrorHandler);
</code></pre>
<p>das ganze auf.<br />
Das funktioniert ja auch, nur weiß ich nicht, wie ich jetzt von diesem void ptr heraus den Aufruf der ErrorHandler Funktionen gestalten soll. Wenn ich</p>
<pre><code class="language-cpp">CErrorHandler *pErr = (CErrorHandler*)pErrHdl;
pErr-&gt;GenerateError(12, &quot;File Access Error&quot;);
</code></pre>
<p>mache, dann kompiliert das zwar, linkt aber nicht, weil GenerateError nicht gefunden wird, was auch stimmt, weil der Errorhandler eben nicht mitsamt seinem Code Teil der DLL werden soll.<br />
Ich gebe der DLL also einen Pointer auf eine Funktion. Wie kann ich nun diese Funktion aufrufen, wenn nur deren Definition bekannt ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1532136</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1532136</guid><dc:creator><![CDATA[HydroNom]]></dc:creator><pubDate>Thu, 19 Jun 2008 10:47:37 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Thu, 19 Jun 2008 12:04:51 GMT]]></title><description><![CDATA[<p>Heyho HydroNom,</p>
<blockquote>
<p>Wie kann ich nun diese Funktion aufrufen, wenn nur deren Definition bekannt ist?</p>
</blockquote>
<p>Wie ich das verstehe ist nur die Deklaration bekannt, also die Header in der sich Deine Errorhandler-Klasse befindet - Definition wäre die Implementierung der Methoden an sich, also das, was in den .cpp-Dateien steht. Nur am Rande...</p>
<p>...zu Deinem Problem:</p>
<p>Vielleicht gibt's jetzt zwar einfachere Lösungen, aber mir fallen da momentan nur zwei ein:</p>
<ol>
<li>
<p>Du machst Deinen Error-Handler und seine Methoden <strong>inline</strong>. Allerdings würdest Du das vermutlich nicht wollen, weil der Code dann mit in die DLL compiled wird.</p>
</li>
<li>
<p>Nutze Polymorphie. Mein Ansatz hier wäre der, dass Du Deinen Error-Handler zunächst in eine weitere DLL auslagerst und ihm eine &quot;abstrakte&quot; Basisklasse zugrunde legst. Kurz umrissen:</p>
</li>
</ol>
<p>Zum Beispiel 'errorhandler_base.h':</p>
<pre><code class="language-cpp">class CErrorHandler_Base {
...
    virtual void GenerateError(int i_ErrID, std::string str_ErrText) = 0;
    virtual ~CErrorHandler();
...
};
</code></pre>
<p>Falls Du Dich damit noch nicht so auskennst, das ist nun eine &quot;abstrakte&quot; Basisklasse. Merkmale sind das <strong>virtual</strong> vor der Methode, sowie ZUSÄTZLICH das <strong>= 0</strong> am Ende. Dadurch wird die Methode zu einer <em>Pure Virtual Method</em> und hat den Sinn, das alle Klassen, die von der hier erben, für die endgültige Implementierung der Methode zuständig sind. Wird dies nicht gemacht, wirft der Compiler einen Fehler. Die &quot;abstrakte&quot; Klasse an sich darf die Methode nicht selbst definieren und man kann somit auch kein Objekt von ihr anlegen. Man verwendet diese Art von Basisklasse als Schnittstelle, da garantiert wird, dass gewisse Methoden zur Verfügung stehen MÜSSEN.</p>
<p>In Deinem jetzigen Error-Handler machst Du jetzt nichts anderes, als von dieser Basisklasse zu erben:</p>
<p>Dein jetziger Error-Handler:</p>
<pre><code class="language-cpp">class CErrorHandler : public CErrorHandler_Base {
...
</code></pre>
<p>Den gesamten Handler lagerst Du jetzt in eine DLL aus. Aber wie ist Dein Problem jetzt gelöst? Es ist trotzdem nur noch die DEKLARATION der Klasse bekannt, wie soll der Linker seine Referenzen nun finden? Ganz einfach: Deiner <strong>CTest</strong> übergibst Du statt einem <strong>void</strong>* nun einen Pointer auf <strong>CErrorHandler_Base</strong>, also auf die vorher erstellte &quot;abstrakte&quot; Basisklasse.</p>
<p>Was jetzt noch fehlt ist eine sogenannte &quot;Factory&quot;-Funktion. Sie hat den einzigen Sinn und Zweck, ein Objekt von Deinem Error-Handler anzulegen und einen Zeiger darauf zurückzuliefern. Aber in welches Modul gehört diese &quot;Factory&quot;-Funktion?! In Dein Hauptprogramm? In Deine DLL, oder in die DLL mit Deinem Error-Handler? Logischerweise in letztere, weil sich da &quot;der Code Deiner Methoden befindet&quot;. Diese besagte Funktion ist äußerst banal:</p>
<p>Factory-Function:</p>
<pre><code class="language-cpp">CErrorHandler* getHandler(void) {
   static CErrorHandler instance;
   return &amp;instance;
   }
</code></pre>
<p>Folgende Anmerkungen zu dieser Sache hier: Falls Du ganz gut aufgepasst hast, und ich es Dir gut erklärt habe, spätestens aber jetzt müsste Dir auffallen, dass wir in der Funktion einen Pointer auf <strong>CErrorHandler</strong> zurückgeben, Dein CTest-Konstruktor aber <strong>CErrorHandler_Base</strong> erwartet - und das ist Polymorphie und ist durch die <em>Pure Virtual Method</em> möglich, die als Schnittstelle dient. Bin leider kein guter Lehrer, also les' Dich besser woanders ein, klappt bestimmt besser <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>Jeeeedenfalls kannst Du, sobald Du die Error-Handler-DLL in Deine andere DLL einbindest, über <strong>getHandler()</strong> Deinen Error-Handler bekommen.</p>
<p>Joa, das war jetzt recht schnell hier reingestampft und ich hoffe das funktioniert auch alles so, bzw. löst Dein Problem... Aber vermutlich ist die Lösung etwas umständlich. Ich entschuldige mich bei jedem der sich jetzt die Stirn wegen mir einhämmert :p</p>
<p>EDIT: Hihi, ich sehe gerade, DeSoVoDaMu hat das ja schon weiter oben vorgeschlagen, ich Hammel <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f611.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--expressionless_face"
      title="-__-"
      alt="😑"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1532186</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1532186</guid><dc:creator><![CDATA[PuerNoctis]]></dc:creator><pubDate>Thu, 19 Jun 2008 12:04:51 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Thu, 19 Jun 2008 13:14:06 GMT]]></title><description><![CDATA[<blockquote>
<p>Wie ich das verstehe ist nur die Deklaration bekannt, also die Header in der sich Deine Errorhandler-Klasse befindet - Definition wäre die Implementierung der Methoden an sich, also das, was in den .cpp-Dateien steht. Nur am Rande...</p>
</blockquote>
<p>Danke, verwechsle ich immer</p>
<p>Ansonsten, wenn ich das richtig verstehe, ist der DLL (mit CTest) der Code des ErrorHandler ja aber doch wieder bekannt (über die vorgeschlagene ErrorHandler DLL). Damit bräuchte man ja gar keine zusätzliche Base Klasse, sondern könnte wieder direkt CErrorHandler benutzen. Das ist zwar schonmal ein Teil, aber ich will ja letztendlich erreichen, daß die End-Applikation selber das Errorhandling zur Verfügung stellen kann und sich dabei lediglich an definierte Interfaces zu halten hat.</p>
<p>Was mir jetzt nicht so ganz klar ist: Ich hab deinen Ansatz mal umgesetzt, allerdings <strong>ohne</strong> den Errorhandler in eine DLL auszulagern. DLL und Applikation compilieren und linken. Dem CTest wird der korrekte Pointer auf den angelegten ErrorHandler übergeben, die in der Applikation codierte Funktionalität von GenerateError aber nicht ausgeführt. Aber WAS wird denn dann ausgeführt, irgendwo muß die DLL doch eine Funktionsdeklaration her haben? Wohin werden bei der DLL die Errorhander Funktionen gelinkt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1532250</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1532250</guid><dc:creator><![CDATA[HydroNom]]></dc:creator><pubDate>Thu, 19 Jun 2008 13:14:06 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Thu, 19 Jun 2008 13:34:46 GMT]]></title><description><![CDATA[<blockquote>
<p>Aber WAS wird denn dann ausgeführt, irgendwo muß die DLL doch eine Funktionsdeklaration her haben? Wohin werden bei der DLL die Errorhander Funktionen gelinkt?</p>
</blockquote>
<p>Würde auch gerne wissen was da ausgeführt wird... Sollte die Referenz auf die Methode in Deiner CTest-Instanz ins Leere laufen, dürfte normalerweise ein Laufzeitfehler auftreten... interessant......</p>
<p>Da ich jetzt schnell Feierabend mach, guck ich mir das, sofern zwischenzeitlich niemand ne korrektur zu obigem Code hat, mal an.</p>
<p>Bis denne,<br />
PuerNoctis <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="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1532270</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1532270</guid><dc:creator><![CDATA[PuerNoctis]]></dc:creator><pubDate>Thu, 19 Jun 2008 13:34:46 GMT</pubDate></item><item><title><![CDATA[Reply to Callback aus einer DLL on Thu, 19 Jun 2008 15:16:05 GMT]]></title><description><![CDATA[<p>Aaah, hab' gerade gemerkt, dass meine &quot;Factory&quot;-Funktion nen kleinen aber entscheidenden Fehler hatte. Der Rückgabewert muss vom Typ der Basisklasse sein - das eigentliche Objekt das zurückgegeben wird aber vom Event-Handler-Typ. Also so:</p>
<pre><code class="language-cpp">CErrorHandler_Base* getHandler(void) {
   static CErrorHandler instance;
   return &amp;instance;
   }
</code></pre>
<p>Hab's bei mir mal nachgestellt und es hat funktioniert (allerdings mit GCC und Shared Objects und nicht mit DLLs).</p>
<p>Hilft das?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1532373</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1532373</guid><dc:creator><![CDATA[PuerNoctis]]></dc:creator><pubDate>Thu, 19 Jun 2008 15:16:05 GMT</pubDate></item></channel></rss>