Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As the error message says, you must use <code>&amp;StartHand::MouseButton</code> syntax to get a pointer to a member function (ptmf); this is simply mandated as part of the language.</p> <p>When using a ptmf, the function you are calling, glutMouseFunc in this case, must also expect to get a ptmf as a callback, otherwise using your non-static MouseButton won't work. Instead, a common technique is for callbacks to work with a user-supplied <code>void*</code> context, which can be the instance pointer&mdash;but the library doing the callbacks must explicitly allow this parameter. It's also important to make sure you match the ABI expected by the external library (the <em>handle_mouse</em> function below).</p> <p>Since glut <em>doesn't</em> allow user-supplied context, you have to use another mechanism: associate your objects with glut's current window. It does provide a way to get the "current window", however, and I've used this to associate a <code>void*</code> with the window. Then you simply need to create a <a href="http://en.wikipedia.org/wiki/Trampoline_%28computers%29" rel="nofollow noreferrer">trampoline</a> to do the type conversion and call the method.</p> <p>Machinery:</p> <pre><code>#include &lt;map&gt; int glutGetWindow() { return 0; } // make this example compile and run ##E## typedef std::pair&lt;void*, void (*)(void*,int,int,int,int)&gt; MouseCallback; typedef std::map&lt;int, MouseCallback&gt; MouseCallbacks; MouseCallbacks mouse_callbacks; extern "C" void handle_mouse(int button, int state, int x, int y) { MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow()); if (i != mouse_callbacks.end()) { // should always be true, but possibly not // if deregistering and events arrive i-&gt;second.second(i-&gt;second.first, button, state, x, y); } } void set_mousefunc( MouseCallback::first_type obj, MouseCallback::second_type f ) { assert(obj); // preconditions assert(f); mouse_callbacks[glutGetWindow()] = MouseCallback(obj, f); //glutMouseFunc(handle_mouse); // uncomment in non-example ##E## handle_mouse(0, 0, 0, 0); // pretend it's triggered immediately ##E## } void unset_mousefunc() { MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow()); if (i != mouse_callbacks.end()) { mouse_callbacks.erase(i); //glutMouseFunc(0); // uncomment in non-example ##E## } } </code></pre> <p>Example:</p> <pre><code>#include &lt;iostream&gt; struct Example { void MouseButton(int button, int state, int x, int y) { std::cout &lt;&lt; "callback\n"; } static void MouseButtonCallback( void* self, int button, int state, int x, int y ) { static_cast&lt;Example*&gt;(self)-&gt;MouseButton(button, state, x, y); } }; int main() { Example obj; set_mousefunc(&amp;obj, &amp;Example::MouseButtonCallback); return 0; } </code></pre> <p>Notice that you don't call <em>glutMouseFunc</em> directly anymore; it is managed as part of <em>[un]set_mousefunc</em>.</p> <hr> <p>Just in case it isn't clear: I've rewritten this answer so it should work for you and so that it avoids the C/C++ linkage issue being debated. It will compile and run as-is (without glut), and it should work with glut with only minor modification: comment or uncomment the 4 lines marked <code>##E##</code>.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload