tag:blogger.com,1999:blog-2715968472735546962.post4027023004490328417..comments2023-12-14T02:21:18.222+01:00Comments on Bannalia: trivial notes on themes diverse: Passing capturing C++ lambda functions as function pointersJoaquín M López Muñozhttp://www.blogger.com/profile/08579853272674211100noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-2715968472735546962.post-6184787224295870312018-05-28T22:23:10.883+02:002018-05-28T22:23:10.883+02:00Hi Joaquín,
Thank you very much for the awesome p...Hi Joaquín, <br />Thank you very much for the awesome post! It helped me a lot...Guilherme Paulinohttps://www.blogger.com/profile/09659588755525510424noreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-46377443210239190172018-01-26T10:30:17.257+01:002018-01-26T10:30:17.257+01:00Thank you Hamed! Fixed.Thank you Hamed! Fixed.Joaquín M López Muñozhttps://www.blogger.com/profile/08579853272674211100noreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-37983279289694082082018-01-26T05:19:53.092+01:002018-01-26T05:19:53.092+01:00Thank you for the great post.
There is a minor ty...Thank you for the great post.<br /><br />There is a minor typo in your code that makes the compiler unhappy. <br /><br />std::function is missing parentheses after void.<br /><br />void do_something(std::function callback)<br />{<br /> ...<br /> callback();<br />}Hamedhttps://www.blogger.com/profile/16741948718447967413noreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-77422269548373001602017-05-31T10:17:21.278+02:002017-05-31T10:17:21.278+02:00This cannot do in portable C++ as far as I know. T...This cannot do in portable C++ as far as I know. Take a look at Win32 thunking mechanisms such as very crelary described at http://www.codeguru.com/cpp/misc/misc/assemblylanguage/article.php/c12667/Thunking-in-Win32.htmJoaquín M López Muñozhttps://www.blogger.com/profile/08579853272674211100noreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-26344559086775123312017-05-30T14:27:04.739+02:002017-05-30T14:27:04.739+02:00That's exactly my use case. I need to pass a n...That's exactly my use case. I need to pass a non-static member function as a callback to GLUT. It accepts no callback argument, and the function itself should accept no arguments (it's void (*)(void) ).<br /><br />I CANNOT make the function static, as it NEEDS access to data that differs from one object instance to another.<br />I also can't just refer to the object instance statically, e.g. in a global variable, because there are multiple instances and each one might use its own member function as the callback from time to time.<br /><br />So, what I need is something that will create, during runtime, a "wrapper" as a function with no arguments, that will call the member function on a specific instance. Of course those will need to be two separate global functions (let's say I have two instances), because there would be no other way for them to "know" which object to work with other than to "embed" the reference to it in the function's code. (That's also why there would NEED to be 2 functions at 2 different addresses - they NEED to result in different void(*)() pointers).<br /><br />I thought the combination of std::bind / std::function does exactly that. But when tried calling target<>() on it, it returned a null pointer, basically saying the function object is NOT compatible with void(*)(void).<br /><br />So, how do I solve this? I know for sure that languages like Java, C# etc do exactly that - each closure (anonymous interface with implementation, and similar things for Java) creates its own copy, with its own address (reference) and data. Why does C++ simply not work the same?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-88483470821915408242016-08-02T10:09:48.056+02:002016-08-02T10:09:48.056+02:00Yes, you can pass the context in a little ad-hoc s...Yes, you can pass the context in a little ad-hoc structure, but this probably requires more boilerplate code than the technique I present in the post; as for readability, I find this more readable (at the end, lambda functions are provided precisely to elminate context-holding structs), but your mileage may vary.<br /><br />When your callback framework does not accept any void* (or similar type-erased arg) where you can pass additional context for the callback function, you're out of luck and have to resort to something else.Joaquín M López Muñozhttps://www.blogger.com/profile/08579853272674211100noreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-86928152532491264752016-07-29T20:26:54.202+02:002016-07-29T20:26:54.202+02:00I am not sure that I understand the reasons behind...I am not sure that I understand the reasons behind this technique. If I read your code correctly, you are passing capturing lambda instance as an argument to non-capturing lambda. Why not pass the state (things you want to capture) directly, or create a little struct for them? It would be so much more readable.<br /><br />Also, wen you are interfacing with old code that uses function pointers, you have rarely the comfort of passing arbitrary arguments to your callback. Usually the signature is given and there is no way to pass additional stuff.<br /><br />As an example, I am working with GLFW that defines bunch of callbacks using function pointers. One of the callbacks is defines as:<br /><br />typedef void(* GLFWmousebuttonfun) (GLFWwindow *, int, int, int)<br /><br />In this case you end up using globals.Marekhttps://www.blogger.com/profile/01329814159153964451noreply@blogger.comtag:blogger.com,1999:blog-2715968472735546962.post-55199403733911756612016-07-29T11:00:55.543+02:002016-07-29T11:00:55.543+02:00Great post! I was planning on writing a relatedpoa...Great post! I was planning on writing a relatedpoat, but the clever thunk approach is even better than I had planned. It would be cool to generalize/genericize this to callback that take other arguments besides the void* user_data (as most do). <br />A.S.https://www.blogger.com/profile/16913096271184629282noreply@blogger.com