<?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[boost::function beim ersten Aufruf erst zuweisen]]></title><description><![CDATA[<p>Ich möchte mir das Linken während der Laufzeit gegen eine dynamische Bibliothek etwas vereinfachen und hab mir dafür einen kleinen Wrapper geschrieben:</p>
<pre><code class="language-cpp">template&lt;class T&gt;
class WeakFunction : public boost::function&lt;T&gt; {
public:
	WeakFunction(const char* const name, const char* const libName) : name_(name), libName_(libName)
	{
	}
	void Load()
	{
		static void* handle = dlopen(libName_, RTLD_LAZY);
		if(!handle)
		{
			throw WeakLinkingError(std::string(&quot;Could not open &quot;) + libName_ + &quot;.&quot;);
		}
		static_cast&lt;boost::function&lt;T&gt;*&gt;(this)-&gt;operator=(reinterpret_cast&lt;T*&gt;(dlsym(handle, name_)));
		if(!*this)
		{
			throw WeakLinkingError(std::string(&quot;Could not find &quot;) + name_ + &quot; in &quot; + libName_ + &quot;.&quot;);
		}
	}
private:
	const char* const name_;
	const char* const libName_;
};

// Beispiel:
WeakFunction&lt;void(ALsizei, ALuint*)&gt; alGenBuffers(&quot;alGenBuffers&quot;, &quot;OpenAL32.dll&quot;);
</code></pre>
<p>Das Problem ist jetzt, dass ich, bevor die Funktion aufgerufen wird, einmal die Load funktion aufrufen muss. Besser wäre es natürlich, wenn die Funktion dies automatisch tut, wenn sie das erste Mal aufgerufen wird. Ist das überhaupt möglich? Wenn ja, wie?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/261770/boost-function-beim-ersten-aufruf-erst-zuweisen</link><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 02:47:53 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/261770.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 23 Feb 2010 16:42:18 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 16:42:18 GMT]]></title><description><![CDATA[<p>Ich möchte mir das Linken während der Laufzeit gegen eine dynamische Bibliothek etwas vereinfachen und hab mir dafür einen kleinen Wrapper geschrieben:</p>
<pre><code class="language-cpp">template&lt;class T&gt;
class WeakFunction : public boost::function&lt;T&gt; {
public:
	WeakFunction(const char* const name, const char* const libName) : name_(name), libName_(libName)
	{
	}
	void Load()
	{
		static void* handle = dlopen(libName_, RTLD_LAZY);
		if(!handle)
		{
			throw WeakLinkingError(std::string(&quot;Could not open &quot;) + libName_ + &quot;.&quot;);
		}
		static_cast&lt;boost::function&lt;T&gt;*&gt;(this)-&gt;operator=(reinterpret_cast&lt;T*&gt;(dlsym(handle, name_)));
		if(!*this)
		{
			throw WeakLinkingError(std::string(&quot;Could not find &quot;) + name_ + &quot; in &quot; + libName_ + &quot;.&quot;);
		}
	}
private:
	const char* const name_;
	const char* const libName_;
};

// Beispiel:
WeakFunction&lt;void(ALsizei, ALuint*)&gt; alGenBuffers(&quot;alGenBuffers&quot;, &quot;OpenAL32.dll&quot;);
</code></pre>
<p>Das Problem ist jetzt, dass ich, bevor die Funktion aufgerufen wird, einmal die Load funktion aufrufen muss. Besser wäre es natürlich, wenn die Funktion dies automatisch tut, wenn sie das erste Mal aufgerufen wird. Ist das überhaupt möglich? Wenn ja, wie?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860181</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860181</guid><dc:creator><![CDATA[joomoo]]></dc:creator><pubDate>Tue, 23 Feb 2010 16:42:18 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 16:48:11 GMT]]></title><description><![CDATA[<p>joomoo schrieb:</p>
<blockquote>
<p>Das Problem ist jetzt, dass ich, bevor die Funktion aufgerufen wird, einmal die Load funktion aufrufen muss. Besser wäre es natürlich, wenn die Funktion dies automatisch tut, wenn sie das erste Mal aufgerufen wird. Ist das überhaupt möglich? Wenn ja, wie?</p>
</blockquote>
<p>operator() definieren der beim ersten call dlopen macht und nachher dann eben an function&lt;T&gt;::operator() weiter gibt.</p>
<p>uU ist es nötig dafür eine Manager Klasse zu schreiben die mehrfaches dlopen abfängt.</p>
<p>die signatur des operator() kannst du dir von function&lt;T&gt; ja geben lassen...</p>
<p>PS:<br />
function objekte werden nicht polymorph verwendet, deshalb ist ein verdecken des operator() kein problem.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860184</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860184</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Tue, 23 Feb 2010 16:48:11 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 16:48:14 GMT]]></title><description><![CDATA[<p>Kannst du dich auf wenige Funktionssignaturen beschränken oder willst du diesbezüglich generisch bleiben? Mir fällt nämlich nur gerade das Überschreiben des <code>operator()</code> ein (wenn notwendig initialisieren und dann Basisklassenfunktion aufrufen). Mir scheint, zu dem Zweck wäre auch Aggregation besser als Vererbung geeignet.</p>
<p>Initialisierung im Konstruktor ist keine Möglichkeit?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860185</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860185</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Tue, 23 Feb 2010 16:48:14 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 16:51:23 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>operator() definieren der beim ersten call dlopen macht und nachher dann eben an function&lt;T&gt;::operator() weiter gibt.</p>
</blockquote>
<p>Wie löse ich das Problem, dass ich ja nicht weiß, wieviele Argumente operator() hat?</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Initialisierung im Konstruktor ist keine Möglichkeit?</p>
</blockquote>
<p>Leider nicht, denn die Funktionen werden Global erstellt und dann würde es ja schon beim Programmstart eine Exception geben, die ich nicht abfangen kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860188</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860188</guid><dc:creator><![CDATA[joomoo]]></dc:creator><pubDate>Tue, 23 Feb 2010 16:51:23 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 16:59:31 GMT]]></title><description><![CDATA[<p>joomoo schrieb:</p>
<blockquote>
<p>Wie löse ich das Problem, dass ich ja nicht weiß, wieviele Argumente operator() hat?</p>
</blockquote>
<p>Mit momentanem C++-Standard sehe ich ausser dem Überladen etlicher Funktionen keine Möglichkeit, deshalb auch die Frage, ob du generisch bleiben müsstest. Der notwendige Code kann mit Präprozessortricks (Boost.Preprocessor) zwar klein gehalten werden, aber im Grunde genommen ist das immer noch nicht sehr schön.</p>
<p>In C++0x wirds Variadic Templates geben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860191</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860191</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Tue, 23 Feb 2010 16:59:31 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 17:02:28 GMT]]></title><description><![CDATA[<p>joomoo schrieb:</p>
<blockquote>
<p>Wie löse ich das Problem, dass ich ja nicht weiß, wieviele Argumente operator() hat?</p>
</blockquote>
<p>AH, ich dachte function liefert das irgendwie leicht - aber das geht ja nicht. Mein Fehler.</p>
<p>Ist n bisschen haesslich, aber solange es keine variadic templates gibt ist das ja immer so <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>WeakFunction erbt von WeakFunctionHelper&lt;function&lt;T&gt;::arity, function&lt;T&gt;&gt;</p>
<p>dann musst du halt für 0-N argumente spezialisieren...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860192</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860192</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Tue, 23 Feb 2010 17:02:28 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 17:48:31 GMT]]></title><description><![CDATA[<p>Das einzige was ich mir jetzt noch vorstellen könnte wäre so etwas:</p>
<pre><code class="language-cpp">template&lt;class T&gt; 
class WeakFunction { 
public: 
    WeakFunction(const char* const name, const char* const libName) : name_(name), libName_(libName), function_()
    { 
    } 
    void Load() 
    { 
        static void* handle = dlopen(libName_, RTLD_LAZY); 
        if(!handle) 
        { 
            throw WeakLinkingError(std::string(&quot;Could not open &quot;) + libName_ + &quot;.&quot;); 
        } 
        function_ = reinterpret_cast&lt;T*&gt;(dlsym(handle, name_)); 
        if(!function_) 
        { 
            throw WeakLinkingError(std::string(&quot;Could not find &quot;) + name_ + &quot; in &quot; + libName_ + &quot;.&quot;); 
        } 
    } 

    boost::function&lt;T&gt; &amp; operator(){
         if( !function_ ){
            Load();
         }
         return function_;
    }

private: 
    const char* const name_; 
    const char* const libName_; 
    boost::function&lt;T&gt; function_;
};
</code></pre>
<p>Damit müsstest du dann so aufrufen:</p>
<pre><code class="language-cpp">WeakFunction&lt;void(ALsizei, ALuint*)&gt; alGenBuffers(&quot;alGenBuffers&quot;, &quot;OpenAL32.dll&quot;);

alGenBuffers()(0, 0);
</code></pre>
<p>Edit: // Some Logic fix</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860202</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860202</guid><dc:creator><![CDATA[evilissimo]]></dc:creator><pubDate>Tue, 23 Feb 2010 17:48:31 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 17:58:36 GMT]]></title><description><![CDATA[<p>Also Variadic Templates sind kein Problem, benutze GCC 4.4. Ich bin jetzt so weit gekommen:</p>
<pre><code class="language-cpp">std::map&lt;std::string, void*&gt; handles_;

template&lt;typename ReturnType, typename... Args&gt;
class WeakFunction {
public:
	WeakFunction(const char* const name, const char* const libName) : name_(name), libName_(libName)
	{
	}
	ReturnType operator()(Args... args)
	{
		static bool loaded = false;
		if(!loaded)
		{
			Load();
		}
		return function_(args...);
	}
	void Load()
	{
		decltype(handles_.end()) i;
		if((i = handles_.find(libName_)) == handles_.end()) // library hasn't been loaded yet?
		{
			static void* handle = dlopen(libName_.c_str(), RTLD_LAZY);
			if(!handle)
			{
				throw WeakLinkingError(std::string(&quot;Could not open &quot;) + libName_ + &quot;.&quot;);
			}
			i-&gt;second = handle;
		}
		function_ = reinterpret_cast&lt;boost::add_pointer&lt;ReturnType(Args...)&gt;::type&gt;(dlsym(i-&gt;second, name_.c_str())); // Problem
		if(!function_)
		{
			throw WeakLinkingError(std::string(&quot;Could not find &quot;) + name_ + &quot; in &quot; + libName_ + &quot;.&quot;);
		}
	}
private:
	boost::function&lt;ReturnType(Args...)&gt; function_;
	const std::string name_;
	const std::string libName_;
};
</code></pre>
<p>Das Problem liegt in der mit &quot;// Problem&quot; markierten Zeile.</p>
<pre><code>55|error: expected type-specifier|
55|error: expected '&gt;'|
55|error: expected '('|
55|error: expected ')' before ';' token|
</code></pre>
<p>Wenn ich das mit add_pointer weglasse geht's, nur dann ist es ein ungültiger cast. Ich krieg das nicht gecastet, hab auch schon typdefs oder ein simples * versucht - ohne Erfolg. Jemand nen Tipp? Sieht für mich nach nem Bug in GCC aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860209</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860209</guid><dc:creator><![CDATA[joomoo]]></dc:creator><pubDate>Tue, 23 Feb 2010 17:58:36 GMT</pubDate></item><item><title><![CDATA[Reply to boost::function beim ersten Aufruf erst zuweisen on Tue, 23 Feb 2010 18:55:17 GMT]]></title><description><![CDATA[<p>dlopen/dlclose unterhalten selbst einen Referenzzähler auf Bibliotheken, die Handle-Map sollte also nicht notwendig sein.</p>
<p>Ich finge das etwa so an:</p>
<pre><code class="language-cpp">#include &lt;functional&gt;
#include &lt;iostream&gt;
#include &lt;stdexcept&gt;
#include &lt;string&gt;

#include &lt;dlfcn.h&gt;
#include &lt;unistd.h&gt;

struct link_error : public std::invalid_argument {
  link_error() : std::invalid_argument(dlerror()) { }
};

class dll_handle {
public:
  dll_handle(std::string const &amp;dll_name)
    : name_  (dll_name),
      handle_(0) { }

  dll_handle(dll_handle const &amp;rhs)
    : name_(rhs.name_),
      handle_(0) {
    if(rhs.handle_) {
      open();
    }
  }

  ~dll_handle() {
    try {
      close();
    } catch(link_error const &amp;e) {
      std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
    }
  }

  void open() {
    if(!handle_) {
      handle_ = dlopen(name_.c_str(), RTLD_LAZY);
      if(!handle_) {
        throw link_error();
      }
    }
  }

  void close() {
    if(handle_ &amp;&amp; dlclose(handle_) != 0) {
      throw link_error();
    }
  }

  void *symbol(std::string const &amp;symbol_name) {
    open();
    void *sym = dlsym(handle_, symbol_name.c_str());

    if(!sym) {
      throw link_error();
    }

    return sym;
  }

private:
  std::string  name_;
  void        *handle_;
};

template&lt;typename T&gt; class weak_function;
template&lt;typename R, typename... A&gt; class weak_function&lt;R(A...)&gt; {
public:
  weak_function(std::string const &amp;dll, std::string const &amp;symbol)
    : dll_        (dll),
      symbol_name_(symbol),
      fo_         () { }

  void link_symbol() {
    if(!fo_) {
      R (*sym)(A...);

      *reinterpret_cast&lt;void**&gt;(&amp;sym) = dll_.symbol(symbol_name_);

      fo_ = sym;
    }    
  }

  R operator()(A... a) {
    link_symbol();
    return fo_.operator()(a...);
  }

private:
  dll_handle  dll_;
  std::string symbol_name_;

  std::function&lt;R(A...)&gt; fo_;
};

int main() {
  weak_function&lt;pid_t(void)&gt; wf(&quot;/lib/libc.so.6&quot;, &quot;getpid&quot;);
  weak_function&lt;pid_t(void)&gt; wf2(&quot;/lib/libc.so.6&quot;, &quot;foobarbazqux&quot;);

  std::cout &lt;&lt; wf() &lt;&lt; std::endl;
  std::cout &lt;&lt; getpid() &lt;&lt; std::endl;

  wf2();
}
</code></pre>
<p>Allerdings ist das eine ziemlich grobe Angelegenheit. Ein großes Designproblem ist 1. Kopiersemantik und 2. const-correctness. Wenn ich etwa eine Funktion der Form</p>
<pre><code class="language-cpp">void call(weak_function&lt;void()&gt; const &amp;func) { func(); }
</code></pre>
<p>habe, wie soll sich func verhalten, wenn die Funktion noch nicht geladen ist? Wahrscheinlich könnte man die Brechstangenmethode (mutable) in diesem Fall sogar ganz gut vertreten, allerdings kommt das auf die weiteren Umstände an.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1860249</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1860249</guid><dc:creator><![CDATA[seldon]]></dc:creator><pubDate>Tue, 23 Feb 2010 18:55:17 GMT</pubDate></item></channel></rss>