{"id":41133,"date":"2004-01-09T07:00:00","date_gmt":"2004-01-09T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/01\/09\/why-do-member-functions-need-to-be-static-to-be-used-as-a-callback\/"},"modified":"2004-01-09T07:00:00","modified_gmt":"2004-01-09T07:00:00","slug":"why-do-member-functions-need-to-be-static-to-be-used-as-a-callback","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040109-00\/?p=41133","title":{"rendered":"Why do member functions need to be &quot;static&quot; to be used as a callback?"},"content":{"rendered":"<p><a HREF=\"http:\/\/weblogs.asp.net\/oldnewthing\/archive\/2004\/01\/08\/48616.aspx\">\nAs we learned yesterday<\/a>,\nnonstatic member functions take a secret &#8220;this&#8221; parameter, which makes\nthem incompatible with the function signature required by Win32 callbacks.\nFortunately, nearly all callbacks provide some way of providing context.\nYou can shove the &#8220;this&#8221; pointer into the context so you can reconstruct\nthe source object.  Here&#8217;s an example:<\/p>\n<p><pre>\nclass SomeClass {\n ...\n static DWORD CALLBACK s_ThreadProc(LPVOID lpParameter)\n {\n  return ((SomeClass*)lpParameter)-&gt;ThreadProc();\n }\n DWORD ThreadProc()\n {\n  ... fun stuff ...\n }\n};\n<\/pre>\n<\/p>\n<p>\nSome callback function signatures place the context parameter\n(also known as &#8220;reference data&#8221;) as the first parameter.  How\nconvenient, for the secret &#8220;this&#8221; parameter is also the first\nparameter.  Looking at\n<a HREF=\"http:\/\/weblogs.asp.net\/oldnewthing\/archive\/2004\/01\/08\/48616.aspx\">\nthe various calling conventions available to us<\/a>,\nit sure\nlooks like the <code>__stdcall<\/code> calling convention\nfor <b>member functions<\/b> matches our desired stack layout\nrather well.\nLet&#8217;s take <code><a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/dllproc\/base\/waitortimercallback.asp\">WAITORTIMERCALLBACK<\/a><\/code>\nfor example:\n<\/p>\n<table BORDER=\"0\">\n<col STYLE=\"padding-left: 1pc;padding-right: 1pc\">\n<col STYLE=\"padding-right: 1pc\">\n<col STYLE=\"padding-left: 1pc;padding-right: 1pc\">\n<col STYLE=\"padding-right: 1pc\">\n<col STYLE=\"padding-left: 1pc;padding-right: 1pc\">\n<tr>\n<th COLSPAN=\"2\">__stdcall callback<\/th>\n<th COLSPAN=\"2\">__stdcall method call<\/th>\n<th COLSPAN=\"2\">thiscall method call<\/th>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">.. rest of stack ..<\/td>\n<td><\/td>\n<td STYLE=\"border: solid 1px buttonshadow\">.. rest of stack ..<\/td>\n<td><\/td>\n<td STYLE=\"border: solid 1px buttonshadow\">.. rest of stack ..<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">TimerOrWaitFired<\/td>\n<td><\/td>\n<td STYLE=\"border: solid 1px buttonshadow\">TimerOrWaitFired<\/td>\n<td><\/td>\n<td STYLE=\"border: solid 1px buttonshadow\">TimerOrWaitFired<\/td>\n<td>&lt;- ESP<\/td>\n<\/tr>\n<tr>\n<td STYLE=\"border: solid 1px buttonshadow\">lpParameter<\/td>\n<td>&lt;- ESP<\/td>\n<td STYLE=\"border: solid 1px buttonshadow\">this<\/td>\n<td>&lt;- ESP<\/td>\n<\/tr>\n<\/table>\n<p>\nWell, &#8220;thiscall&#8221; doesn&#8217;t match, but the two &#8220;__stdcall&#8221;s do.\nFortunately the compiler is smart enough to recognize this and\ncan optimize the <code>s_ThreadProc<\/code> static method to\nnothing if you just give it enough of a nudge:<\/p>\n<p><pre>\nclass SomeClass {\n ...\n static DWORD CALLBACK s_ThreadProc(LPVOID lpParameter)\n {\n  return ((SomeClass*)lpParameter)-&gt;ThreadProc();\n }\n DWORD <font COLOR=\"red\">__stdcall<\/font> ThreadProc()\n {\n  ... fun stuff ...\n }\n};\n<\/pre>\n<\/p>\n<p>\nIf you look at the code generation for the <code>s_ThreadProc<\/code>\nfunction, you&#8217;ll see that has been reduced to nothing but a\njump instruction, since the compiler has realized that the two\ncalling conventions coincide here so there is no actual translation\nto do.\n<\/p>\n<p><pre>\n?s_ThreadProc@SomeClass@@SGKPAX@Z PROC NEAR\n  jmp     ?ThreadProc@SomeClass@@QAGKXZ\n?s_ThreadProc@SomeClass@@SGKPAX@Z ENDP\n<\/pre>\n<p>\nNow some people would take this one step further and just\ncast the second parameter to <code>CreateThread<\/code>\nto <code>LPTHREAD_START_ROUTINE<\/code>\nand get rid of the helper <code>s_ThreadProc<\/code> function\nentirely.\n<b>I strongly advise against this.<\/b>\nI have seen too many people cause trouble by miscasting\nfunction pointers; more on this in a future entry.\n<\/p>\n<p>\nAlthough we took advantage above of a coincidence between the two\n<code>__stdcall<\/code> calling conventions,\nwe did not <b>rely<\/b> on it.\nIf the coincidence in calling conventions fails to occur,\nthe code is still correct.\nThis is important when it comes time to port this code to\nanother architecture, one where the coincidence may longer\nbe true!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As we learned yesterday, nonstatic member functions take a secret &#8220;this&#8221; parameter, which makes them incompatible with the function signature required by Win32 callbacks. Fortunately, nearly all callbacks provide some way of providing context. You can shove the &#8220;this&#8221; pointer into the context so you can reconstruct the source object. Here&#8217;s an example: class SomeClass [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2],"class_list":["post-41133","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>As we learned yesterday, nonstatic member functions take a secret &#8220;this&#8221; parameter, which makes them incompatible with the function signature required by Win32 callbacks. Fortunately, nearly all callbacks provide some way of providing context. You can shove the &#8220;this&#8221; pointer into the context so you can reconstruct the source object. Here&#8217;s an example: class SomeClass [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/41133","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=41133"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/41133\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=41133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=41133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=41133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}