<?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[Methodezeiger in Funktionenzeiger umwandeln?]]></title><description><![CDATA[<p>Ich arbeite an einem Projekt, bei dem ich eine fremde API benutzen muss. Ich habe zwar die Möglichkeit diese API umzuschreiben, aber dies möchte ich wirklich nur im äußersten Notfall machen.</p>
<p>Nun zu meinem Problem. Von der API möchte ich eine Funktion aufrufen, die als Parameter einen Funktionenzeiger erwartet.</p>
<pre><code class="language-cpp">// Definition des Funtionenzeigers
typedef int (*int_FctPtr)(const int&amp;);

// Zu benutzende Funktion der API
void macheEtwas(int_FctPtr f, /*Weitere Parameter*/);
</code></pre>
<p>Wenn ich in meinem Projekt eine globalle Funktion anlege mit obiger Signatur und diese der Funktion macheEtwas übergebe, funktionert alles bestens. Nun ist meine Funktion f aber von wechselnden Daten abhängig, die in einem Objekt gespeichert sind. Dieses Objekt kann ich aber der Funktion f nicht übergeben, da so deren Signatur geändert werden würde. Also dachte ich mir, man legt eine Instanzmethode im Objekt selber an, welche man dann übergibt.</p>
<pre><code class="language-cpp">class TestClass
{
private:
  double daten;
public:
  TestClass(double);
  int f( const int&amp; );
};

.
.
.

typedef int (TestClass::*methode)(const int&amp;);
methode F = &amp;TestClass::f;

TestClass test(1.0);
macheEtwas(test.*F, /*Weitere Parameter*/);
</code></pre>
<p>Dies ergibt den Compilerfehler:</p>
<blockquote>
<p>error C2664: 'macheEtwas': Konvertierung des Parameters 1 von 'überladener Funktionstyp' in 'int_FctPtr' nicht möglich<br />
Der konvertierte Ausdruck ist nicht gültig</p>
</blockquote>
<p>Mittlerweile weiß ich, dass Instanzmethoden und Funktionen eben doch nicht die gleiche Signatur haben, aber es muss doch möglich sein, einen Funktionenzeiger zu erzeugen und zu übergeben, wenn man das entsprechende Objekt im Hauptprogramm kennt.</p>
<p>Ich habe auch folgendes probiert:</p>
<pre><code class="language-cpp">TestClass param(0.0);
int F( const int&amp; x )
{
	return param.f(x);
}

.
.
.

// Im Hauptprogramm
TestClass test(1.0);
param = test;
macheEtwas(F, /*Weitere Daten*/);
</code></pre>
<p>Das funktioniert zwar, aber ist <em>quick</em> und sowas von <em>dirty</em>, dass ich es gleich wieder verworfen habe.</p>
<p>Bevor die Frage aufkommen, ich benutze Visual C++ 2005 (daran gibt es leider nichts zu rütteln). Das Projekt beschäftigt sich unter anderem mit dem Lösen nichtlinearer Gleichungssysteme und dabei sollen nun die Werte wechselnder Funktionen an verschiedenen Stellen ausgewertet werden. Ich hoffe das verdeutlicht die Notwendigkeit von Funktions- und Methodenzeigern. Macht euch bitte keine Gedanken über den Datentyp. Ich habe int in obige Codeschnippseln aufgrund der Lesbarkeit gewählt.</p>
<p>Zu guter Letzt danke ich jedem, der etwas zu Lösung des Problems beitragen kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/191781/methodezeiger-in-funktionenzeiger-umwandeln</link><generator>RSS for Node</generator><lastBuildDate>Sun, 27 Sep 2026 05:43:41 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/191781.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 06 Sep 2007 13:08:58 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 13:08:58 GMT]]></title><description><![CDATA[<p>Ich arbeite an einem Projekt, bei dem ich eine fremde API benutzen muss. Ich habe zwar die Möglichkeit diese API umzuschreiben, aber dies möchte ich wirklich nur im äußersten Notfall machen.</p>
<p>Nun zu meinem Problem. Von der API möchte ich eine Funktion aufrufen, die als Parameter einen Funktionenzeiger erwartet.</p>
<pre><code class="language-cpp">// Definition des Funtionenzeigers
typedef int (*int_FctPtr)(const int&amp;);

// Zu benutzende Funktion der API
void macheEtwas(int_FctPtr f, /*Weitere Parameter*/);
</code></pre>
<p>Wenn ich in meinem Projekt eine globalle Funktion anlege mit obiger Signatur und diese der Funktion macheEtwas übergebe, funktionert alles bestens. Nun ist meine Funktion f aber von wechselnden Daten abhängig, die in einem Objekt gespeichert sind. Dieses Objekt kann ich aber der Funktion f nicht übergeben, da so deren Signatur geändert werden würde. Also dachte ich mir, man legt eine Instanzmethode im Objekt selber an, welche man dann übergibt.</p>
<pre><code class="language-cpp">class TestClass
{
private:
  double daten;
public:
  TestClass(double);
  int f( const int&amp; );
};

.
.
.

typedef int (TestClass::*methode)(const int&amp;);
methode F = &amp;TestClass::f;

TestClass test(1.0);
macheEtwas(test.*F, /*Weitere Parameter*/);
</code></pre>
<p>Dies ergibt den Compilerfehler:</p>
<blockquote>
<p>error C2664: 'macheEtwas': Konvertierung des Parameters 1 von 'überladener Funktionstyp' in 'int_FctPtr' nicht möglich<br />
Der konvertierte Ausdruck ist nicht gültig</p>
</blockquote>
<p>Mittlerweile weiß ich, dass Instanzmethoden und Funktionen eben doch nicht die gleiche Signatur haben, aber es muss doch möglich sein, einen Funktionenzeiger zu erzeugen und zu übergeben, wenn man das entsprechende Objekt im Hauptprogramm kennt.</p>
<p>Ich habe auch folgendes probiert:</p>
<pre><code class="language-cpp">TestClass param(0.0);
int F( const int&amp; x )
{
	return param.f(x);
}

.
.
.

// Im Hauptprogramm
TestClass test(1.0);
param = test;
macheEtwas(F, /*Weitere Daten*/);
</code></pre>
<p>Das funktioniert zwar, aber ist <em>quick</em> und sowas von <em>dirty</em>, dass ich es gleich wieder verworfen habe.</p>
<p>Bevor die Frage aufkommen, ich benutze Visual C++ 2005 (daran gibt es leider nichts zu rütteln). Das Projekt beschäftigt sich unter anderem mit dem Lösen nichtlinearer Gleichungssysteme und dabei sollen nun die Werte wechselnder Funktionen an verschiedenen Stellen ausgewertet werden. Ich hoffe das verdeutlicht die Notwendigkeit von Funktions- und Methodenzeigern. Macht euch bitte keine Gedanken über den Datentyp. Ich habe int in obige Codeschnippseln aufgrund der Lesbarkeit gewählt.</p>
<p>Zu guter Letzt danke ich jedem, der etwas zu Lösung des Problems beitragen kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360216</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360216</guid><dc:creator><![CDATA[ak131554]]></dc:creator><pubDate>Thu, 06 Sep 2007 13:08:58 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 13:13:16 GMT]]></title><description><![CDATA[<p>Jetzt mal nur ne anektdote zu methodenzeiger in funktionszeiger unwandeln:<br />
Das hab ich früher immer mit inline assembler gemacht, und dann ecx entsprechend gesetzt...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360221</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360221</guid><dc:creator><![CDATA[dfgdgdgf]]></dc:creator><pubDate>Thu, 06 Sep 2007 13:13:16 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:03:59 GMT]]></title><description><![CDATA[<p>@dfgdgdgf: Assembler klingt auch ziemlich brachial, aber da ich jeden Tipp begrüße, möchte ich dich bitten, das näher auszuführen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360260</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360260</guid><dc:creator><![CDATA[ak131554]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:03:59 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:10:43 GMT]]></title><description><![CDATA[<p>nunja die funktion erwartet ja einen funtionszeiger, und ist auch fest, also die kannst du nicht mehr verändern. Die anketdote mit dem assembler, war für methoden, wo ich selber die memberfunktion aufrufe.</p>
<p>Für solche sachen ist deine lösung mit der hilfsfunktion am besten geeignet. Man kann nämlich nicht der aufgerufenen funktion sagen, dass sie die memberfunktion mit einem entsprechend gesetzten ecx aufrufen soll. Daraus folgt, dass wenn man mit assembler(oder sonstwie) den methodenzeiger übergibt, die funktion die zielfunktion aufruft, und dabei ecx nicht setzt. Und nun könnte eben die API intern ecx für irgeneine berechnung benutztnen, und dann zeigt ecx(respektive this) auf garnichts oder etwas, das nich vom typ TestClass ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360266</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360266</guid><dc:creator><![CDATA[etgertet]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:10:43 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:20:29 GMT]]></title><description><![CDATA[<p>Erstmal: Wenn irgendwer einen Funktionszeiger erwartet, kannst du ihm keinen Methodenzeiger übergeben - da fehlt der Bezug zum this-Objekt.</p>
<p>Wenn du die Arbeitsfunktion nicht ändern kannst, fällt mir eigentlich nur der Weg über eine Hilfsfunktion ein (in der Art, die du als &quot;quick and dirty&quot; eingestuft hast) - eventuell in leichten Variationen. (oder eventuell solche Assambler-Spielereien)<br />
Wenn du eine Möglichkeit hast, die Arbeitsfunktion zu ändern, dann solltest du sie umstellen auf Funktoren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360272</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360272</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:20:29 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:21:31 GMT]]></title><description><![CDATA[<p>Wer sagt überhaupt, dass auf seiner Plattform this in ecx übergeben wird?</p>
<p>Zum Thema: Sprachmittel gibt es da keine. Die Callback-Funktion erwartet nunmal nur einen Parameter, und eine passende Memberfunktion erwartet zwei (this implizit zusätzlich). Du kannst aber, wenn es nur ein Objekt gibt, zu dem die Methode aufgerufen wird, eine Hilfsfunktion schreiben (Achtung: Ansatz, nichts ausgereiftes)</p>
<pre><code class="language-cpp">Klasse* caller;
int hilfsFunk(const int&amp; x) { return caller-&gt;funk(x); }

/* Aufruf */
caller = this;
macheWas( &amp;::hilfsFunk, /* ... */ );
</code></pre>
<p>Von Assembler-Hacks würde ich grundsätzlich die Finger lassen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360273</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360273</guid><dc:creator><![CDATA[LordJaxom]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:21:31 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:33:23 GMT]]></title><description><![CDATA[<p>Jetzt nich böse gemeint aber hast du seinen Post überhaupt durchgelesen?</p>
<pre><code class="language-cpp">class TestClass
{
private:
  double daten;
public:
  TestClass(double);
  int f( const int&amp; );
};

TestClass param(0.0);
int F( const int&amp; x )
{
	return param.f(x);
}

.
.
.

// Im Hauptprogramm
TestClass test(1.0);
param = test;
macheEtwas(F, /*Weitere Daten*/);
</code></pre>
<p>Und das mit ecx war auf einem x86 OS auf eine x64 prozessor.<br />
Und das natürlich nur bei __thiscall.</p>
<p>Aber natürlich ist der o.g., oder dein Ansatz besser. Z.B. kann der x64 compiler kein inline assembler mehr, so ein mist...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360289</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360289</guid><dc:creator><![CDATA[ertetetee]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:33:23 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:41:18 GMT]]></title><description><![CDATA[<p>ertetetee schrieb:</p>
<blockquote>
<p>Jetzt nich böse gemeint aber hast du seinen Post überhaupt durchgelesen?</p>
</blockquote>
<p>Nicht aufmerksam zumindest. Hab ich mir bei Unregs, deren Namen ich nichtmal aussprechen kann abgewöhnt. Hast aber Recht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360293</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360293</guid><dc:creator><![CDATA[LordJaxom]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:41:18 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 14:46:37 GMT]]></title><description><![CDATA[<p>Naja, man könnte natürlich (je nach Signatur der Funktion) auch einfach die Adresse des Objekts übergeben und in der CallbackFunktion entsprechend zurück-Casten. Dazu muss man aber &quot;beide Enden&quot; unter Kontrolle haben und &quot;die API&quot; diesen Wert nur &quot;durchschleusen&quot;.</p>
<p>Gruß,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360302</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360302</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Thu, 06 Sep 2007 14:46:37 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 15:44:19 GMT]]></title><description><![CDATA[<p>Ich weiss nicht ob folgendes Funktioniert. Die Moeglichkeit der Hilfsfunktion wurd ja oben schon gegeben, allerdings hast du dann das Problem, dass du das Objekt, fuer das du die Methode aufrufen willst, in der Funktion fest angeben musst. Um das zu umgehen koennte ich mit folgendes vorstellen:</p>
<pre><code class="language-cpp">// Definition des Funtionenzeigers
typedef int (*int_FctPtr)(const int&amp;);

// Zu benutzende Funktion der API
void macheEtwas(int_FctPtr f, /*Weitere Parameter*/);

class TestClass
{
private:
  double daten;
public:
  TestClass(double);
  int f( const int&amp; );
};

typedef int (T::funptr*)(const int&amp;)

template &lt;TestClass* tcptr, funptr fun&gt;
int replace(const int&amp; i)
{ return tcptr-&gt;funptr(i); }

TestClass test(1.0);
macheEtwas(&amp;replace&lt;&amp;test, &amp;TestClass::f&gt;, /*Weitere Parameter*/);
</code></pre>
<p>Vielleicht sind die operatoren nicht alle Korrekt, aber in der Art sollte es moeglich sein, das Objekt und die Funktion als template-parameter verpackt an die API zu verkaufen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360336</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360336</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Thu, 06 Sep 2007 15:44:19 GMT</pubDate></item><item><title><![CDATA[Reply to Methodezeiger in Funktionenzeiger umwandeln? on Thu, 06 Sep 2007 18:04:32 GMT]]></title><description><![CDATA[<p>Also kurz gesagt: sauber geht es nicht.</p>
<p>2 Möglichkeiten wurden ja schon genannt:</p>
<ol>
<li>
<p>Thunks (die &quot;inline assembler&quot; Version -- kann man aber auch machen indem man direkt die Code-Bytes in ein Array schreibt und den Zeiger auf das Array dann auf den entsprechenden Funktions-Zeiger-Typ castet). Natürlich muss man dazu dann den Instruction-Cache flushen, und natürlich die DEP (data execution prevention) beschwichtigen.</p>
</li>
<li>
<p>Globale Variablen bzw. &quot;fest verdrahtete&quot; Objekt-Zeiger. Auch doof, dafür einfacher und kein Ärger mit verschiedenen Plattformen (32 Bit, 64 Bit etc.).</p>
</li>
</ol>
<p>Weitere möglichkeit weiss ich auch keine.</p>
<p>----</p>
<p>Wenn du dich für Thunks interessierst, in der ATL werden solche Thunks verwendet (um die WindowProc an das entsprechende Objekt weiterzuleiten).<br />
Kannst du dir angucken wie das dort gemacht wird, und zwar in &quot;atlstdthunk.h&quot;.<br />
Die Klassen dort wirst du wahrscheinlich nicht 1:1 übernehmen können, sollte dir aber ne Vorstellung vermitteln wie man sowas macht.</p>
<p>EDIT: das beste wäre sicher die API so zu ändern dass du beim Registrieren des Callbacks einen void* mitgeben kannst, den du dann als Parameter beim Callback wieder mitbekommst. Dann ist das Weiterleiten ein Kinderspiel, da du den void* z.B. direkt als &quot;this&quot; Zeiger verwenden kannst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1360410</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1360410</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Thu, 06 Sep 2007 18:04:32 GMT</pubDate></item></channel></rss>