<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://community.element14.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Forum - Recent Threads</title><link>https://community.element14.com/products/devtools/software/f/forum</link><description /><dc:language>en-US</dc:language><generator>Telligent Community 12</generator><lastBuildDate>Thu, 13 Mar 2025 20:41:48 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://community.element14.com/products/devtools/software/f/forum" /><item><title>C++ callbacks and templates</title><link>https://community.element14.com/thread/54719?ContentTypeID=0</link><pubDate>Sat, 15 Jun 2024 10:50:00 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:95e9f4be-67c8-415a-81cf-d67f3fd1ce81</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>17</slash:comments><comments>https://community.element14.com/thread/54719?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I&amp;#39;m experimenting: can I use&amp;nbsp;a method of a particular object as a callback?&amp;nbsp;This can be used in typical callback situations, e.g.:&amp;nbsp;in a&amp;nbsp;UART driver. But also&amp;nbsp;in interrupt handlers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lightweight: small runtime cost, low firmware&amp;nbsp;hit.&amp;nbsp;Can be used for tiny&amp;nbsp;embedded systems.&lt;/li&gt;
&lt;li&gt;reusable: don&amp;#39;t assume parameters and types for the handler, when writing this little framework -&amp;gt; C++ templates&lt;/li&gt;
&lt;li&gt;hip -&amp;gt; object oriented, modern C++ constructs&lt;/li&gt;
&lt;li&gt;type safe -&amp;gt; again C++ templates&lt;/li&gt;
&lt;li&gt;allow a classic C function, a lambda, a static class method or an object method as handler&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;example: Raspberry&amp;nbsp;Pico blinky using this design&lt;/p&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span style="color:#af00db;"&gt;#include&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;lt;new&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span style="color:#af00db;"&gt;#include&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span style="color:#af00db;"&gt;#include&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;quot;pico/stdlib.h&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#000000;font-size:150%;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;import callbackmanager;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#000000;font-size:150%;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#267f99;"&gt;uint32_t&lt;/span&gt; &lt;span style="color:#001080;"&gt;delay_ms&lt;/span&gt; = &lt;span style="color:#098658;"&gt;250&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#000000;font-size:150%;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span style="color:#001080;"&gt;callbackmanager&lt;/span&gt;::Callback&amp;lt;&lt;span style="color:#0000ff;"&gt;void&lt;/span&gt;&amp;gt; cb;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; &lt;span style="color:#795e26;"&gt;main&lt;/span&gt;() {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;gpio_init&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;PICO_DEFAULT_LED_PIN&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;gpio_set_dir&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;PICO_DEFAULT_LED_PIN&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;, &lt;/span&gt;&lt;span style="color:#0070c1;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;GPIO_OUT&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;cb&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;.&lt;/span&gt;&lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;set&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;([]() {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;static&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;bool&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt; &lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;state&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt; = &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;gpio_put&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;(&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;PICO_DEFAULT_LED_PIN&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;, &lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;state&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt; = !&lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;state&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;});&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#af00db;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;while&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt; (&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;true&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;cb&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;sleep_ms&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;(&lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;delay_ms&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:arial, helvetica, sans-serif;font-size:inherit;"&gt;&lt;span style="color:#000000;"&gt;project:&amp;nbsp;[View:/cfs-file/__key/communityserver-discussions-components-files/126/2133.pico_5F00_callback_5F00_blink.zip:640:360]&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="mcetoc_1i0dng6rh0"&gt;Callback&amp;nbsp;template class&lt;/h1&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The template callback class. This is in essence the whole mechanism. A generic class that allows you to register and call event handler functions, lambda&amp;#39;s and methods.&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:2793c371-9a96-43d1-8524-51f6e47409cf:type=c_cpp&amp;text=%23include%20%3Cfunctional%3E%0A%0A%2F%2F%20concept%20guards%20what%20types%20of%20return%20values%20we%20can%20handle%0Atemplate%3Ctypename%20R%3E%0Aconcept%20Callbackable%20%3D%20%0A%09std%3A%3Ais_void%3CR%3E%3A%3Avalue%20%7C%7C%0A%09std%3A%3Ais_arithmetic_v%3CR%3E%20%7C%7C%0A%09std%3A%3Ais_class_v%3CR%3E%3B%0A%09%0Atemplate%20%3CCallbackable%20R%2C%20typename...%20Args%3E%0Aclass%20Callback%20%7B%0A%09using%20callbackfunction_t%20%3D%20std%3A%3Afunction%3CR%28Args...%29%3E%3B%09%0Apublic%3A%0A%09Callback%28%29%20%3A%20callback_%28nullptr%29%2C%20isSet%28false%29%7B%7D%0A%0A%09inline%20void%20set%28callbackfunction_t%20callback%29%20%7B%0A%09%20%20%20%20callback_%20%3D%20callback%3B%0A%09%09isSet%20%3D%20true%3B%0A%09%7D%0A%0A%09inline%20void%20unset%28%29%20%7B%0A%09%09callback_%20%3D%20nullptr%3B%0A%09%09isSet%20%3D%20false%3B%0A%09%7D%0A%0A%09inline%20bool%20is_set%28%29%20%7B%0A%09%09return%20isSet%3B%09%09%0A%09%7D%0A%0A%09%2F%2A%0A%09%20%2A%20R%20can%20be%20an%20arithmetic%20type%2C%20an%20object%2C%20or%20void%0A%09%20%2A%2F%0A%09inline%20R%20operator%28%29%28Args...%20args%29%20%7B%0A%09%09if%20constexpr%20%28std%3A%3Ais_void%3CR%3E%3A%3Avalue%29%20%7B%20%20%2F%2F%20void%0A%09%09%09if%20%28%21is_callback_set%29%20%7B%0A%09%09%09%09return%3B%0A%09%09%09%7D%20else%20%7B%0A%09%09%09%09%28callback_%29%28args...%29%3B%0A%09%09%09%7D%0A%09%09%7D%20else%20if%20constexpr%20%28std%3A%3Ais_class%3CR%3E%3A%3Avalue%29%20%7B%20%2F%2F%20object%0A%09%09%09if%20%28%21is_callback_set%29%20%7B%0A%09%09%09%09return%20R%28%29%3B%0A%09%09%09%7D%20else%20%7B%0A%09%09%09%09return%20%28callback_%29%28args...%29%3B%0A%09%09%09%7D%0A%09%09%7D%20else%20%7B%20%2F%2F%20not%20void%20nor%20object%0A%09%09%09if%20%28%21is_callback_set%29%20%7B%0A%09%09%09%09return%200%3B%20%2F%2F%20R%20can%20only%20be%20a%20arithmetic%20type.%200%20should%20work%20as%20default.%0A%09%09%09%7D%20else%20%7B%0A%09%09%09%09return%20%28callback_%29%28args...%29%3B%0A%09%09%09%7D%0A%09%09%7D%0A%0A%09%7D%0A%09%0Aprivate%3A%0A%09callbackfunction_t%20callback_%3B%0A%09bool%20isSet%3B%0A%7D%3B]&lt;/p&gt;
&lt;p&gt;This generic class allows for handlers that pass any amount of parameters. No assumption of the types.&lt;/p&gt;
&lt;p&gt;When we use the class in our code, we &amp;#39;ll tell it what the parameters are, and their type. For this blog, I am going to pass it 2 integers. The return value is also an integer.&lt;/p&gt;
&lt;p&gt;&lt;code&gt; Callback&amp;lt;int, int, int&amp;gt; cb;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the declaration above, the first int is the return value type, the 2 others are parameter 1 and 2.&amp;nbsp;Once you write this code, the object cb will only accept handler methods that take two integers as parameter, and return an integer.&lt;/p&gt;
&lt;h1 id="mcetoc_1i0dnovsf1"&gt;Example of class that will handle the callback&lt;/h1&gt;
&lt;p&gt;This could be a gio class (blinky a led when an interrupt occurred?), a GUIwidget, or a business object. Typical guidelines apply: a handler should be swift. In particular if it&amp;#39;s an interrupt handler.&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:4b853d3e-7d6c-4fcb-a69e-3482825079e3:type=c_cpp&amp;text=class%20MyClass%20%7B%0D%0Apublic%3A%0D%0A%20%20%20%20%20%20int%20handler%28int%20num1%2C%20int%20num2%29%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0D%0A%20%20%20%20%20%20%7D%0D%0A%7D%3B]&lt;/p&gt;
&lt;p&gt;The example does not do a lot today. It just sums up the two integers passed. But as a POC this will do.&lt;/p&gt;
&lt;p&gt;Actual code using the two&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:3efa4a2c-b3c4-4a28-a2a4-d1d55783f960:type=c_cpp&amp;text=%23include%20%3Ccstdio%3E%0A%0Aint%20main%28%29%0A%7B%0A%20%20%20%20MyClass%20myClass%3B%0A%0A%20%20%20%20Callback%3Cint%2C%20int%2C%20int%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20capture%20myClass%20and%20call%20the%20member%20method%0A%20%20%20%20cb.set%28%5B%26myClass%5D%28int%20num1%2C%20int%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20myClass.handler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20a%20%3D%204%3B%0A%20%20%20%20int%20b%20%3D%205%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%20%2F%2F%20We%20might%20be%20on%20an%20embedded%20system%2C%20use%20printf%28%29%20and%20not%20std%3A%3Acout%0A%7D]&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;table border="1" width="499" height="27"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;em&gt;Why use a lambda to pair the handler and Callback ?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the code, I did not learn the MyClass how to register itself. And the Callback doesn&amp;#39;t know anything about who or what&amp;nbsp;it &amp;#39;ll call. These classes (and their objects) are unaware of each other. Loose coupling.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Callback&amp;lt;int, int, int&amp;gt; cb;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cb.set([&amp;amp;myClass](int num1, int num2) -&amp;gt; int {&lt;br /&gt;&amp;nbsp; return myClass.handler(num1, num2);&lt;br /&gt; })&lt;/code&gt;&lt;code&gt;;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the application logic, I tie the two together. The lambda function code (the anonymous function, starting with the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;[&lt;/span&gt;, and ending with the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;}&lt;/span&gt; above), is used as the vehicle to hold the code that the Callback object will execute when needed.&lt;/p&gt;
&lt;p&gt;The lambda function could as well be a straigtforward piece of code, not related to any object:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Callback&amp;lt;int, int, int&amp;gt; cb;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cb.set([](int num1,&amp;nbsp;int&amp;nbsp;num2) -&amp;gt; int {&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&amp;nbsp; return num1 + num2;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;});&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Or we could pass completely different executable code. As long as the lambda matches the signature given when instantiating the Callback class.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In an embedded system,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;myClass would be one of your application objects.&lt;/li&gt;
&lt;li&gt;cb could be part of a driver, or the HAL layer&lt;/li&gt;
&lt;li&gt;cb.set() would be called by you, to register the handler&lt;/li&gt;
&lt;li&gt;cb.call() would be done by the driver, or HAL ISR, when it wants to notify you (call your callback handler)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the case of this example, it will execute myClass.handler(). If you &amp;#39;d have many MyClass objects, it would call the exact one that&amp;#39;s registered in with&amp;nbsp;set().&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:413px;max-width:500px;" alt=" " height="413" src="https://community.element14.com/resized-image/__size/1000x826/__key/communityserver-discussions-components-files/126/uml.jpg" width="500" /&gt;&lt;br /&gt;&lt;span style="font-size:75%;"&gt;&lt;em&gt;Example use of the callback class in an embedded application&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anything special?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This approach allows to write a reusable callback system. It is type safe. But it does not assume&amp;nbsp;what the type is of the object it &amp;#39;ll call the handler off. (Or if it&amp;#39;s actually an object).&lt;br /&gt;It&amp;#39;s a small amount of code, that performs a&amp;nbsp;function that&amp;nbsp;you regularly need in an embedded or event driven design.&lt;/p&gt;
&lt;table border="1" width="499" height="27"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;em&gt;What does type-safe mean in this context?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If your interrupt handler assumes a function that passes 2 integers, and you pass it a callback function that has&amp;nbsp;different parameters,&lt;br /&gt;you get a compile time error. Your code will not build, because the handler is not compatible.&lt;/p&gt;
&lt;p&gt;And you get all of that, without having to specify the number of variables, and their types, in the Callback class code. We get a reusable class. Type&amp;nbsp;safe.&amp;nbsp;Without the need to foresee all possible combinations.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;this library now also works for Arduino (tested with IDE2, and an Arduino MKT GSM 1400)&lt;/em&gt;&lt;/p&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p dir="auto"&gt;For Arduino, you can &lt;a href="https://gist.github.com/jancumps/6dbc257c80911270775ee9d44a5131ee/raw/e046870456af25c6ddb79e65504d4ed77d79c3c8/callbackmanager.h" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;download callbackmanager.h&lt;/a&gt; to your computer, then use Sketch -&amp;gt; Add File ... to get the callbackmanager included to your project. &lt;br /&gt;Add this line to your sketch:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;quot;callbackmanager.h&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p dir="auto"&gt;I added a sketch to test the callback manager to this gist: &lt;a href="https://gist.githubusercontent.com/jancumps/6dbc257c80911270775ee9d44a5131ee/raw/df2641f47183aefc09261c25b77c7ddff0f336af/test_arduino.ino" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;test_arduino.ino&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:360px;max-width:640px;" alt=" " src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/pastedimage1721652589582v2.png" /&gt;&lt;br /&gt;&lt;span style="font-size:75%;"&gt;Arduinos that use the gcc-avg toolchain are not supported (UNO, Mega, the original basic Nano)&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;shortcuts:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="text-decoration:line-through;"&gt;I assume fixed return value type. A richer implementation can use template for that too, and should allow void.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;em&gt;edit: this works&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="text-decoration:line-through;"&gt;I pass arguments by value. A better design would also allow pass by reference. And to pass&amp;nbsp;const references.&lt;/span&gt;&amp;nbsp;&lt;em&gt;edit: this works&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="text-decoration:line-through;"&gt;should I use a shared pointer, so that&amp;nbsp;I can never call the handler of an object that no longer exists? (solved by alternative: provide an unset() method).&lt;/span&gt;&amp;nbsp;&lt;em&gt;edit: the class no longer uses pointers&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;it only allows to call one handler. Good for ISR use. But in an event driven design, you may want to register more handlers. I prefer just one handler. simple scope, simple responsibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Inspiration:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I started from &lt;a href="https://blog.mbedded.ninja/programming/languages/c-plus-plus/callbacks/" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;this example by&amp;nbsp;Geoffrey Hunter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;mbed&amp;#39;s &lt;a href="https://os.mbed.com/docs/mbed-os/v6.16/mbed-os-api-doxy/_callback_8h_source.html" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Callback class&lt;/a&gt;, although I didn&amp;#39;t use any of the code&lt;/li&gt;
&lt;li&gt;cplusplus&amp;#39; &lt;a href="//%20https//cplusplus.com/reference/functional/function/function/#example" data-e14adj="t"&gt;tutorial for std::function&lt;/a&gt;, to validate if it works for static class member, object member, classic C function and lambda function.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Code is &lt;a href="https://github.com/jancumps/callbackmanager" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;available on github&lt;/a&gt;. Additional assets&amp;nbsp;&lt;a href="https://gist.github.com/jancumps/6dbc257c80911270775ee9d44a5131ee" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;available on Gist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CMakeLists.txt to build an example program:&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:ca5e5f4f-89fe-4045-91d5-5cfb53ff9704:type=text&amp;text=cmake_minimum_required%28VERSION%203.28%29%0A%0Aproject%28callbackmanager%20C%20CXX%20ASM%29%0A%0A%23%20GoogleTest%20requires%20at%20least%20C%2B%2B14%0Aset%28CMAKE_CXX_STANDARD%2026%29%0Aset%28CMAKE_CXX_STANDARD_REQUIRED%20ON%29%0Aset%28CMAKE_CXX_FLAGS%20%22%24%7BCMAKE_CXX_FLAGS%7D%20-fmodules-ts%20-fcommon%22%29%0A%0Aadd_executable%28%24%7BCMAKE_PROJECT_NAME%7D%29%0Atarget_sources%28%24%7BCMAKE_PROJECT_NAME%7D%0A%20%20%20%20%20%20%20%20PUBLIC%0A%20%20%20%20%20%20%20%20%24%7BCMAKE_CURRENT_SOURCE_DIR%7D%2Fexample%2Fcallback_examples.cpp%0A%29%0Atarget_sources%28%24%7BCMAKE_PROJECT_NAME%7D%0A%20%20%20%20%20%20%20%20PUBLIC%0A%20%20%20%20%20%20%20%20FILE_SET%20cxx_modules%20TYPE%20CXX_MODULES%20FILES%0A%20%20%20%20%20%20%20%20%24%7BCMAKE_CURRENT_SOURCE_DIR%7D%2Fcallbackmanager.cpp%0A%29%0A%0Atarget_link_libraries%28%20%24%7BCMAKE_PROJECT_NAME%7D%0A%29]&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I test this code in&amp;nbsp;&amp;nbsp;[mention:5b356e0658814266b1c94f99fba9084c:46448885d0e64133bbfbf0cd7b0fd6f7]&amp;nbsp;&lt;br /&gt;edit 20250208: I converted it to a c++ module:&amp;nbsp;[mention:4bba44c64c404a9998ef8303509171f3:f7d226abd59f475c9d224a79e3f0ec07]&amp;nbsp;&lt;/p&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/227429?ContentTypeID=1</link><pubDate>Thu, 13 Mar 2025 20:41:48 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:489a241e-a019-4525-8306-aa8f7b09c724</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/227429?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Is this expensive?&lt;/p&gt;
&lt;p&gt;The callback manager class consumes 20 bytes&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/pastedimage1741898063218v1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The code that&amp;#39;s executed does not change. If you have to perform the logic, the code has to be there, regardless if you use the callback.&lt;/p&gt;
&lt;p&gt;There is a price of using std::function.&amp;nbsp;Not flyweight but still light. A few calls between invoking the callback and executing the actual callback handler.&amp;nbsp;Not impacting on an ARM controller, even the tiny ones.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you use a real time system and you worry about using this in a tight loop: the&amp;nbsp;clock ticks to invoke the handler are deterministic and hard. Your profiler can check if your code can perform in the available timeslot.&lt;/p&gt;
&lt;p&gt;Using one of the smaller ATMELs? Performance impact is not relevant. There&amp;#39;s no C toolchain for those controllers that supports this design.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/227420?ContentTypeID=1</link><pubDate>Thu, 13 Mar 2025 17:39:44 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:4ddc7d73-31eb-4926-9f7b-62b0a2a94993</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/227420?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;example: Raspberry&amp;nbsp;&lt;strong&gt;Pico Blinky&lt;/strong&gt; using this design&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;span style="color:#af00db;"&gt;#include&lt;span style="color:#0000ff;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;lt;new&amp;gt;&lt;br /&gt;&lt;/span&gt;#include&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;span style="color:#af00db;"&gt;#include&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#a31515;"&gt;&amp;quot;pico/stdlib.h&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;import callbackmanager;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;font-size:150%;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#267f99;"&gt;uint32_t&lt;/span&gt; &lt;span style="color:#001080;"&gt;delay_ms&lt;/span&gt; = &lt;span style="color:#098658;"&gt;250&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;font-size:150%;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;span style="color:#001080;"&gt;callbackmanager&lt;/span&gt;::Callback&amp;lt;&lt;span style="color:#0000ff;"&gt;void&lt;/span&gt;&amp;gt; cb;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; &lt;span style="color:#795e26;"&gt;main&lt;/span&gt;() {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;gpio_init&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;PICO_DEFAULT_LED_PIN&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;gpio_set_dir&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;PICO_DEFAULT_LED_PIN&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0070c1;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;GPIO_OUT&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;cb&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;set&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;([]() {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;static&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;bool&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;state&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt; = &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;gpio_put&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;PICO_DEFAULT_LED_PIN&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;state&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt; = !&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;state&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;});&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="color:#af00db;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&amp;nbsp; while&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;cb&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#795e26;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;sleep_ms&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#001080;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;delay_ms&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;vscode project:&amp;nbsp;&lt;span style="font-size:150%;"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:Consolas, &amp;#39;Courier New&amp;#39;, monospace;"&gt;&lt;span&gt;&lt;a href="https://community.element14.com/cfs-file/__key/communityserver-discussions-components-files/126/pico_5F00_callback_5F00_blink.zip"&gt;community.element14.com/.../pico_5F00_callback_5F00_blink.zip&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/227339?ContentTypeID=1</link><pubDate>Fri, 07 Mar 2025 15:38:05 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:e939fd64-382c-4ba1-b1f0-78abca0e770e</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/227339?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Just checked it on an Arduino MKR 1400, with some hardware manipulation. The callbacks do the job.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:490px;max-width:495px;"  height="490" src="https://community.element14.com/resized-image/__size/990x980/__key/communityserver-discussions-components-files/126/pastedimage1741361743669v1.png" width="495" /&gt;&lt;/p&gt;
&lt;p&gt;Until your&amp;nbsp;Arduino&amp;nbsp;Board Manager ships with&amp;nbsp;GCC 10 or later, comment this line in the callbackmanager class definition:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;code&gt;&lt;span&gt;//&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span&gt;requires&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;is_void&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;R&lt;/span&gt;&lt;span&gt;&amp;gt;::value || &lt;/span&gt;&lt;span&gt;std&lt;/span&gt;&lt;span&gt;::is_arithmetic_v&amp;lt;R&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This isn&amp;#39;t supported in the (at the time of writing) version that ships with the MKR boards. The code isn&amp;#39;t needed to operate. It&amp;#39;s a compile time construct that gives a clear error when you try to set a callback handler that isn&amp;#39;t supported*.&lt;/p&gt;
&lt;p&gt;Without this line, you &amp;#39;ll get a&amp;nbsp;compile error too, but it will throw that error at a location where it&amp;#39;s not very clear what&amp;#39;s wrong.&lt;/p&gt;
&lt;p&gt;So: result is the same: compiler throws an error as it should. But that extra line makes it easier to find what&amp;#39;s wrong and remediate.&lt;br /&gt;* the callback manager supports handlers that return a bool, any type of number, most objects that have a default creator and have &amp;quot;return-me capability, or&amp;nbsp; void.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/223643?ContentTypeID=1</link><pubDate>Sun, 01 Sep 2024 17:46:43 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:1a175058-3c9d-47be-81c1-c63c137d7722</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/223643?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I used the mechanism in the &lt;a href="https://community.element14.com/search?q=*#serptag=teseo_c%2B%2B&amp;amp;serpsort=date%20desc" data-e14adj="t"&gt;GPS library that I designed for a ST Micro Teseo GPS IC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s used to call a device specific read, write and reset function, in a device independent library.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222643?ContentTypeID=1</link><pubDate>Mon, 22 Jul 2024 12:57:35 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:13b23538-e4fb-482e-9a23-c7cd11a09d75</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/222643?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;em&gt;this library now also works for Arduino (tested with IDE2, and an Arduino MKT GSM 1400)&lt;/em&gt;&lt;/p&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p dir="auto"&gt;For Arduino, you can&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://gist.github.com/jancumps/6dbc257c80911270775ee9d44a5131ee/raw/e046870456af25c6ddb79e65504d4ed77d79c3c8/callbackmanager.h" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;download callbackmanager.h&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to your computer, then use Sketch -&amp;gt; Add File ... to get the callbackmanager included to your project.&lt;br /&gt;Add this line to your sketch:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;quot;callbackmanager.h&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p dir="auto"&gt;I added a sketch to test the callback manager&amp;nbsp;as a GitHub GIST:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href="https://gist.githubusercontent.com/jancumps/6dbc257c80911270775ee9d44a5131ee/raw/df2641f47183aefc09261c25b77c7ddff0f336af/test_arduino.ino" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;test_arduino.ino&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:360px;max-width:640px;"  src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/0576.pastedimage1721652589582v2.png" /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I expect this will work on the newer ADO boards. The AVR compiler for Arduino UNO / Nano (both use&amp;nbsp;avr-gcc) does not support this. But the Nano IoT (uses arm-gcc) does.&lt;/p&gt;
&lt;p&gt;A&amp;nbsp;Zero and the MKR family work.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222598?ContentTypeID=1</link><pubDate>Fri, 19 Jul 2024 18:55:22 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:8d7adcf5-6eb4-421f-81ad-410aa189432f</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222598?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;a href="https://gist.github.com/jancumps/6dbc257c80911270775ee9d44a5131ee" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;latest version on github gist&lt;/a&gt; allows compilation with lower version GCC (including the Renesas and Arduino toolchains).&lt;/p&gt;
&lt;p&gt;There is no difference at runtime. You &amp;#39;ll only get a little more cryptic error if you use unsupported template types:&lt;br /&gt;an error when the compiler detects that the code can&amp;#39;t handle your type, instead of an error right at the declaration where you define what parameter types you want to use.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: GitHub: automate Raspberry Pico project build verification with GitHub Actions</title><link>https://community.element14.com/thread/222537?ContentTypeID=1</link><pubDate>Mon, 15 Jul 2024 11:57:09 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:3dd2505e-a144-4eeb-9414-ec0983467fc2</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222537?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54818/github-automate-raspberry-pico-project-build-verification-with-github-actions/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&lt;a href="https://community.element14.com/members/cstanton"&gt;cstanton&lt;/a&gt;&amp;nbsp;, can you delete this forum post? It&amp;#39;s now&amp;nbsp;&lt;a href="https://community.element14.com/technologies/code_exchange/b/blog/posts/github-automate-raspberry-pico-project-build-verification-with-github-actions"&gt;GitHub: automate Raspberry Pico project build verification with GitHub Actions&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>GitHub: automate Raspberry Pico project build verification with GitHub Actions</title><link>https://community.element14.com/thread/54818?ContentTypeID=0</link><pubDate>Mon, 15 Jul 2024 09:44:56 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:74c26e56-04b1-4b10-ace7-c8f788accf64</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/54818?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54818/github-automate-raspberry-pico-project-build-verification-with-github-actions/rss?ContentTypeId=0</wfw:commentRss><description>&lt;h1&gt;&lt;span style="background-color:#ff0000;"&gt;Moved to&amp;nbsp;&amp;nbsp;[mention:fd8811585d4a425bb3b0816cf2887d20:f7d226abd59f475c9d224a79e3f0ec07]&amp;nbsp;&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can Make GitHub build your project.&amp;nbsp;I&amp;#39;m using an Action to check out branches and build them, when a pull request is submitted. &lt;br /&gt;I adapted an existing flow from the Raspberry organisation. Here&amp;#39;s what it does&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;check out the branch that&amp;#39;s the source&amp;nbsp;for the pull request&lt;/li&gt;
&lt;li&gt;check out Pico-SDK, the&amp;nbsp;current development branch&lt;/li&gt;
&lt;li&gt;install CMake&lt;/li&gt;
&lt;li&gt;install the arm bare metal GNU toolchain&lt;/li&gt;
&lt;li&gt;build the SDK&lt;/li&gt;
&lt;li&gt;build the project&lt;/li&gt;
&lt;li&gt;react on pull request creation on the main and develop branch.&lt;/li&gt;
&lt;li&gt;make successful compilation a&amp;nbsp;mandatory check for the pull request.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the build fails, the&amp;nbsp;pull request&amp;nbsp;fails. That&amp;#39;s what I try to achieve in this exercise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;developers can check in non-working in feature branches.&lt;/li&gt;
&lt;li&gt;once ready to ask&amp;nbsp;merging with one of the two protected branches (develop or main), code should&amp;nbsp;meet quality requirements and should build.&lt;br /&gt;That&amp;#39;s the moment that you deem your work done, and&amp;nbsp;should be ready for a code review.&lt;br /&gt;If your code breaks the build at this point, you impact others - and maybe the production release. It&amp;#39;s a fail.&lt;/li&gt;
&lt;li&gt;Code reviewers don&amp;#39;t have to spend time validating non-funcioning code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The script I&amp;#39;m using is based on the &lt;a href="https://github.com/raspberrypi/pico-examples/blob/e38b215d2a5259906302a6669043d95af5894d50/.github/workflows/macOS.yml" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;Raspberrry MacOS build for Pico&lt;/a&gt;. I adapted it for Linux.&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" height="112" src="https://community.element14.com/resized-image/__size/996x224/__key/communityserver-discussions-components-files/126/pastedimage1720986004290v1.png" width="498" /&gt;&lt;/p&gt;
&lt;p&gt;Script source of build.yml:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:ee420520-335b-415c-9649-8b8889964dd2:type=text&amp;text=name%3A%20Build%20on%20ubuntu%20against%20pico-sdk%20develop%0Aon%3A%0A%20%20workflow_dispatch%3A%0A%20%20%23push%3A%0A%20%20%23%20%20branches%3A%0A%20%20%23%20%20%20%20-%20%27develop%27%0A%20%20%23%20%20%20%20-%20%27main%27%0A%20%20pull_request%3A%0A%20%20%20%20types%3A%20%5Bopened%2C%20reopened%5D%0A%20%20%20%20branches%3A%0A%20%20%20%20%20%20-%20%27develop%27%0A%20%20%20%20%20%20-%20%27main%27%0A%0Ajobs%3A%0A%20%20build%3A%0A%20%20%20%20runs-on%3A%20ubuntu-latest%0A%20%20%20%20steps%3A%0A%20%20%20%20%0A%20%20%20%20%20%20-%20name%3A%20Clean%20workspace%0A%20%20%20%20%20%20%20%20run%3A%20%7C%0A%20%20%20%20%20%20%20%20%20%20echo%20%22Cleaning%20up%20previous%20run%22%0A%20%20%20%20%20%20%20%20%20%20rm%20-rf%20%22%24%7B%7B%20github.workspace%20%7D%7D%22%0A%20%20%20%20%20%20%20%20%20%20mkdir%20-p%20%22%24%7B%7B%20github.workspace%20%7D%7D%22%0A%20%20%20%20%20%20-%20name%3A%20Checkout%20pico_gps_teseo_i2c%0A%20%20%20%20%20%20%20%20uses%3A%20actions%2Fcheckout%40v4%0A%20%20%20%20%20%20%20%20with%3A%0A%20%20%20%20%20%20%20%20%20%20path%3A%20pico_gps_teseo_i2c%0A%0A%20%20%20%20%20%20-%20name%3A%20Checkout%20pico-sdk%2Fdevelop%0A%20%20%20%20%20%20%20%20uses%3A%20actions%2Fcheckout%40v4%0A%20%20%20%20%20%20%20%20with%3A%0A%20%20%20%20%20%20%20%20%20%20repository%3A%20raspberrypi%2Fpico-sdk%0A%20%20%20%20%20%20%20%20%20%20ref%3A%20develop%0A%20%20%20%20%20%20%20%20%20%20path%3A%20pico-sdk%0A%0A%20%20%20%20%20%20-%20name%3A%20Checkout%20pico-sdk%20submodules%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20working-directory%3A%20%24%7B%7Bgithub.workspace%7D%7D%2Fpico-sdk%0A%20%20%20%20%20%20%20%20run%3A%20git%20submodule%20update%20--init%0A%20%20%20%20%20%20-%20name%3A%20Install%20dependencies%0A%20%20%20%20%20%20%20%20run%3A%20%7C%0A%20%20%20%20%20%20%20%20%20%20sudo%20apt-get%20install%20cmake%0A%20%20%20%20%20%20%20%20%20%20%23curl%20-Lo%20gcc-arm-none-eabi.tar.bz2%20%22https%3A%2F%2Fdeveloper.arm.com%2F-%2Fmedia%2FFiles%2Fdownloads%2Fgnu-rm%2F10.3-2021.10%2Fgcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2%3Frev%3D78196d3461ba4c9089a67b5f33edf82a%26hash%3D5631ACEF1F8F237389F14B41566964EC%22%0A%20%20%20%20%20%20%20%20%20%20%23sudo%20mkdir%20%2Fopt%2Fgcc-arm-none-eabi%0A%20%20%20%20%20%20%20%20%20%20%23sudo%20tar%20xf%20gcc-arm-none-eabi.tar.bz2%20--strip-components%3D1%20-C%20%2Fopt%2Fgcc-arm-none-eabi%0A%20%20%20%20%20%20%20%20%20%20%23echo%20%27export%20PATH%3D%24PATH%3A%2Fopt%2Fgcc-arm-none-eabi%2Fbin%27%20%7C%20sudo%20tee%20-a%20%2Fetc%2Fprofile.d%2Fgcc-arm-none-eabi.sh%0A%20%20%20%20%20%20%20%20%20%20%23export%20PATH%3D%24PATH%3A%2Fopt%2Fgcc-arm-none-eabi%2Fbin%0A%20%20%20%20%20%20%20%20%20%20%23export%20PICO_TOOLCHAIN_PATH%3D%2Fopt%2Fgcc-arm-none-eabi%2Fbin%0A%20%20%20%20%20%20%20%20%20%20%23source%20%2Fetc%2Fprofile%0A%20%20%20%20%20%20%20%20%20%20%23arm-none-eabi-gcc%20--version%0A%20%20%20%20%20%20%20%20%20%20sudo%20apt%20install%20gcc-arm-none-eabi%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20-%20name%3A%20Build%20Project]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Excuses for the&amp;nbsp;formatting. The code editor does not want to accept this code. Click on this &lt;a href="https://github.com/jancumps/pico_gps_teseo_i2c/blob/main/.github/workflows/build.yml" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;link for a better view&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you create this script in the .github/workflows folder, it &amp;#39;ll kick off each time a pull rrequest is opened for main or develop. But it will not impact the pull request.&lt;br /&gt;If you want to make pull requests dependent on successful build, you &amp;#39;ll also hav to create a ruleset for the branch.&lt;/p&gt;
&lt;p&gt;On&amp;nbsp;your repository&amp;#39;s web page on&amp;nbsp;GitHub, select settings -&amp;gt; Rules -&amp;gt; Rulesets.&lt;br /&gt;If the branch(es) you want to protect don&amp;#39;t have a ruleset yet, create one. Else you can update the existing one.&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:283px;max-width:500px;" alt=" " height="283" src="https://community.element14.com/resized-image/__size/1000x566/__key/communityserver-discussions-components-files/126/pastedimage1721035892809v1.png" width="500" /&gt;&lt;/p&gt;
&lt;p&gt;The first checkbox will take care that&amp;nbsp;the branches you want to protect, can only accept commits via a pull request. When you work together as a team, it&amp;#39;s good that branch owners can check code before it&amp;#39;s merged in the code base.&lt;br /&gt;The second check also adds the condition, that the build job must complete in good order.&lt;/p&gt;
&lt;p&gt;A developer that submits a pull request, gets this page:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" height="144" src="https://community.element14.com/resized-image/__size/994x288/__key/communityserver-discussions-components-files/126/pastedimage1720982706863v1.png" width="497" /&gt;&lt;/p&gt;
&lt;p&gt;They don&amp;#39;t have to wait for this to complete. They &amp;#39;d get an email if it failed.&amp;nbsp;Once the job is completed, the reviewer sees the screen capture I posted at the start of this blog. If the job was successful, code review and merge can happen.&lt;/p&gt;
&lt;h3 id="mcetoc_1i2qs7e4m1"&gt;How does it fit in my workflow:&lt;/h3&gt;
&lt;p&gt;I&amp;nbsp;created another action earlier: &amp;nbsp;[mention:4b25dc423d2f4b2fb72ecb0d54b0dfb1:46448885d0e64133bbfbf0cd7b0fd6f7]&amp;nbsp;. Together, the 2 automate a decent part of code management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the build validation described here, when a pull request is made to development or main&lt;/li&gt;
&lt;li&gt;when a pull request to main is accepted and merged by the branch manager (me :) ), the doucmentation is regenerated and published to github.io.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mcetoc_1i2qs77fr0"&gt;Future improvements:&lt;/h3&gt;
&lt;p&gt;I&amp;#39;m considering to let the job create a project release, when a&amp;nbsp;new Version TAG is created in the repository. I&amp;#39;d have to make these changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;add trigger on TAG creation event. Filter on tags that start with &amp;#39;v&amp;#39;.&lt;/li&gt;
&lt;li&gt;change the build type from Debug to Release&lt;/li&gt;
&lt;li&gt;use a GitHub Action to create a release in the repository, and upload the .uf2 file as asset to that release.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Link to&amp;nbsp;&lt;a href="https://community.element14.com/search?q=*#serptag=teseo_c%2B%2B&amp;amp;serpsort=date%20desc" data-e14adj="t"&gt;all posts&lt;/a&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222225?ContentTypeID=1</link><pubDate>Thu, 27 Jun 2024 15:57:46 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:f5ec40f8-9567-4ccb-9b94-d1cf88e5c16b</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222225?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;comment out this &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;requires&lt;/span&gt; line in the template definition.&lt;/p&gt;
&lt;pre&gt;requires std::is_void&amp;lt;R&amp;gt;::value || std::is_arithmetic_v&amp;lt;R&amp;gt;&lt;/pre&gt;
&lt;p&gt;It&amp;#39;s code that doesn&amp;#39;t execute anything but helps the developer to use supported attributes.&lt;br /&gt;The current GNU toolchain for Renesas is 1 version too low for this.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you don&amp;#39;t have this line, and use a non-supported return type for the callback, you &amp;#39;ll get a compile error anyway.&lt;br /&gt;But it &amp;#39;ll be a more cryptic one, at the first line where the code tries to do an operation that your type doesn&amp;#39;t support.&lt;br /&gt;In my template, that will be at the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return 0;&lt;/span&gt; line. That&amp;#39;s the only line that doesn&amp;#39;t work for any type of return value.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222213?ContentTypeID=1</link><pubDate>Thu, 27 Jun 2024 15:21:24 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:a02c18a9-434e-4c46-80f8-3f784e24fc2c</guid><dc:creator>flyingbean</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/222213?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I just got a new board from Renesas. Will try e2 studio after my vacation this Summer.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222095?ContentTypeID=1</link><pubDate>Fri, 21 Jun 2024 19:22:45 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:03079649-33b1-4772-8eef-a1f75426c57e</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222095?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Most of this design only has compile time cost. The only thing that has some runtime cost is the std::function invocation. This part&amp;nbsp;of code:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;(*_callback)(args...);&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;There are four function calls in between this call and the actual execution of the callback function registered. Not a lot of code is executed, but four calls nonetheless.&lt;br /&gt;I&amp;#39;d consider C++ abstractions cheap. But if 4 calls are too much for the design you are working on, this is not your solution.&lt;/div&gt;
&lt;div&gt;We&amp;#39;re not talking a lot of clock ticks though - this is all lean.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;The cheapest way will most likely be to write callback functionality in assembler or using C style (both without type safety and object awareness). On a controller like the Pico, I think that the cost is ignorable in the majority of firmware designs.&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>C++ and templates: callbacks that return a value, or a void</title><link>https://community.element14.com/thread/54742?ContentTypeID=0</link><pubDate>Fri, 21 Jun 2024 16:38:59 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:4e1bda44-73fd-4193-bb9b-e6c83c5309f4</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/54742?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54742/c-and-templates-callbacks-that-return-a-value-or-a-void/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;In C(++), a function can return a value. Or a void. &lt;br /&gt;A function with a return value ends with &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return &lt;strong&gt;&lt;em&gt;X&lt;/em&gt;&lt;/strong&gt;;&lt;/span&gt;.&lt;br /&gt;A function that returns &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;void&lt;/span&gt;, has a last line &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return;&lt;/span&gt;. Without value. (and&amp;nbsp;you don&amp;#39;t have to write that &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return;&lt;/span&gt;, but that doesn&amp;#39;t matter in&amp;nbsp;this discussion)&lt;br /&gt;When using templates, this needs consideration, if you allow the return type to&amp;nbsp; be &amp;quot;templated&amp;quot; and you want to support &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;void&lt;/span&gt; as one of the options for a return value of a member.&lt;/p&gt;
&lt;p&gt;A void function (named a procedure in a lot of programming languages) is different than a function that returns something. Internally and conceptually.&lt;br /&gt;&lt;em&gt;internally&lt;/em&gt;:&amp;nbsp;the return value is a position on the stack. void functions don&amp;#39;t have that position.&lt;br /&gt;&lt;em&gt;conceptually&lt;/em&gt;: ignoring the internally difference, and returning something in a &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;void()&lt;/span&gt; function anyways, breaks the C(++) language. Also not returning a value (of the correct type) in a function that does require a return value, fails to compile.&lt;/p&gt;
&lt;p&gt;I wrote &lt;a href="https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates" data-e14adj="t"&gt;a templated class that can call a callback&lt;/a&gt;. And I wanted it to support returning numbers / bools.&amp;nbsp;&lt;br /&gt;The thing is: when no callback function is set, the class had to work too. It &lt;em&gt;has&lt;/em&gt; to return a value in that case .So I wrote this code:&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:4d286c93-24ed-4546-a90f-6b5a6f687f5b:type=c_cpp&amp;text=%09inline%20R%20call%28Args...%20args%29%20%7B%0D%0A%09%09if%20%28_callback%20%3D%3D%20nullptr%29%20%7B%0D%0A%09%09%09return%200%3B%20%2F%2F%20R%20can%20only%20be%20a%20arithmetic%20type.%200%20should%20work%20as%20default.%0D%0A%09%09%7D%0D%0A%09%09return%20%28%2A_callback%29%28args...%29%3B%0D%0A%09%7D]&lt;/p&gt;
&lt;p&gt;This works great for boolean, integer, float return values. But it you want to support callbacks that don&amp;#39;t have a return value, it will fail.&lt;br /&gt;If R is type void, the compilation will not allow r&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;eturn 0;&lt;/span&gt;. And if R is a number, compilation will not allow &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return;&lt;/span&gt;.&lt;/p&gt;
&lt;h1 id="mcetoc_1i0tq35hb0"&gt;solution: constant expressions&lt;/h1&gt;
&lt;p&gt;In C++ , we can write constant expressions. A condition that&amp;#39;s checked at compile time. If it&amp;#39;s true, the containing block will be compiled. If it&amp;#39;s false, not.&lt;br /&gt;A bit related to the C style&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;#ifdef&lt;/span&gt; , but context aware.&amp;nbsp;A constant expression knows the code it&amp;#39;s acting upon (including parameter types). These constant expressions understand C++ source code.&lt;br /&gt;What they have in common with defines: they both are static: they resolve everything during compilation. They have no runtime cost.&lt;/p&gt;
&lt;p&gt;I use this construct to have different behaviour if the return type of my callback function is void, and when it&amp;#39;s an arithmetic (number) type:&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:5aca7d31-2da0-4e90-91a2-5ffe4f71e25c:type=c_cpp&amp;text=%09%2F%2A%0D%0A%09%20%2A%20R%20can%20either%20be%20an%20arithmetic%20type%2C%20or%20void%0D%0A%09%20%2A%2F%0D%0A%09inline%20R%20call%28Args...%20args%29%20%7B%0D%0A%09%09if%20constexpr%20%28std%3A%3Ais_void%3CR%3E%3A%3Avalue%29%20%7B%0D%0A%09%09%09if%20%28_callback%20%3D%3D%20nullptr%29%20%7B%0D%0A%09%09%09%09return%3B%0D%0A%09%09%09%7D%0D%0A%09%09%09%28%2A_callback%29%28args...%29%3B%0D%0A%09%09%7D%0D%0A%0D%0A%09%09if%20constexpr%20%28%21%20std%3A%3Ais_void%3CR%3E%3A%3Avalue%29%20%7B%0D%0A%09%09%09if%20%28_callback%20%3D%3D%20nullptr%29%20%7B%0D%0A%09%09%09%09return%200%3B%20%2F%2F%20R%20can%20only%20be%20a%20arithmetic%20type.%200%20should%20work%20as%20default.%0D%0A%09%09%09%7D%0D%0A%09%09%09return%20%28%2A_callback%29%28args...%29%3B%0D%0A%09%09%7D%0D%0A%09%7D]&lt;/p&gt;
&lt;p&gt;You can see that when my templated code is configured for a callback function that returns a bool or a number, it &amp;#39;ll use the lower part, and always return a value.&lt;br /&gt;When the template is configured for a void() type of callback (a procedure), it just returns, without a return value.&lt;/p&gt;
&lt;p&gt;This compiles, runs, is type safe and has no runtime impact.&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;if constexpr&lt;/span&gt; gets resolved when you build the code. If your code doesn&amp;#39;t have &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;void()&lt;/span&gt; callbacks, the top part doesn&amp;#39;t get compiled. If it doesn&amp;#39;t have callbacks that expect a return value, the bottom part doesn&amp;#39;t get compiled.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Check my set of test cases below, to see how this works:&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:26697407-1dbe-4730-b1dd-8560c409242e:type=c_cpp&amp;text=%23include%20%3Ccstdio%3E%0A%23include%20%22callbackmanager.h%22%0A%23include%20%3Cstring%3E%0A%0Aclass%20MyClass%20%7B%0Apublic%3A%0A%09inline%20int%20handler%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20const%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20static%20inline%20int%20staticHandler%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0A%20%20%20%20%20%20%7D%0A%7D%3B%0A%0Aint%20functionHandler%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0A%20%20%20%20return%20num1%20%2B%20num2%3B%0A%7D%0A%0Aint%20main%28%29%20%7B%0A%0A%20%20%20%20int%20a%20%3D%204%3B%0A%20%20%20%20int%20b%20%3D%205%3B%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20object%20method%0A%20%20%20%20MyClass%20myClass%3B%0A%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20capture%20myClass%20and%20call%20the%20object%20method%0A%20%20%20%20cb.set%28%5B%26myClass%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20myClass.handler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb.call%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20static%20method%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20call%20the%20static%20method%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20MyClass%3A%3AstaticHandler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb.call%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20C%20function%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20call%20the%20classic%20C%20function%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20functionHandler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb.call%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20pure%20lambda%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%20%3D%20cb.call%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20return%20a%20bool%0A%20%20%20%20Callback%3Cbool%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20bool%20%7B%0A%20%20%20%20%20%20%20%20return%20num1%20%3D%3D%20num2%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20printf%28%22Value%3A%20%25s%5Cn%22%2C%20cb.call%28a%2C%20b%29%20%3F%20%22true%22%20%3A%20%22false%22%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20use%20a%20callback%20that%20returns%20void%0A%20%20%20%20Callback%3Cvoid%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0A%20%20%20%20%20%20%20%20printf%28%22void%20gets%20num1%3A%20%25i%2C%20num2%3A%20%25i%5Cn%22%2C%20num1%2C%20num2%29%3B%0A%20%20%20%20%09fflush%28stdout%29%3B%0A%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%29%3B%0A%20%20%20%20cb.call%28a%2C%20b%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20use%20a%20callback%20that%20returns%20void%2C%20and%20has%20no%20attributes%0A%20%20%20%20Callback%3Cvoid%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28%29%20%7B%0A%20%20%20%20%20%20%20%20printf%28%22void%20with%20no%20parameters%5Cn%22%29%3B%0A%20%20%20%20%09fflush%28stdout%29%3B%0A%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%29%3B%0A%20%20%20%20cb.call%28%29%3B%0A%09%7D%0A%0A%09%2F%2A%0A%09%7B%20%2F%2F%20scenario%3A%20use%20an%20unsupported%20%28non-fundamental%29%20type%20for%20return%20value%20R%0A%09%20%20%2F%2F%20this%20will%20generate%20a%20compile%20error%0A%20%20%20%20Callback%3Cstd%3A%3Astring%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%09%7D%0A%2A%2F%0A%0A%7D]&lt;/p&gt;
&lt;table border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;a constexpr knows &amp;quot;everything&amp;quot; about your code. When you use it in a template class, it will know for what types your project will use that template class.&amp;nbsp;Then it &amp;#39;ll&amp;nbsp;take care that it &amp;#39;ll only send that part of the code to the compiler, that is needed for your project.&lt;/p&gt;
&lt;p&gt;For classes like the one that I&amp;#39;m writing, this is great. My class has no clue how it &amp;#39;ll be used. But I provide logic for a set of scenarios that I want to support.&lt;br /&gt;C++ constructs like &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;constexpr&lt;/span&gt; will take care that this flexibility has no cost when executing the code. All code gets checked at compilation, and needs to pass the strict C++ type checks. But at no cost for the final firmware.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/54725?ContentTypeID=0</link><pubDate>Mon, 17 Jun 2024 15:33:54 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:56a59140-6063-4163-9b05-56117c976f1c</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>7</slash:comments><comments>https://community.element14.com/thread/54725?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;When you use templates in C++, the user can normally plug any C type in a program.&amp;nbsp;For a template class I developed (read &amp;nbsp;[mention:95e9f4be67c8415a81cfd67f3fd1ce81:46448885d0e64133bbfbf0cd7b0fd6f7]&amp;nbsp;), I want to restrict one of the template arguments:&amp;nbsp;R. This is the type of the return value of a callback function.&amp;nbsp;The&amp;nbsp;restriction that I want to impose, is that the function should not return an object, array, string, ... . Numeric and bool types should do. Or&amp;nbsp;return nothing (void).&lt;/p&gt;
&lt;p&gt;I want to be able to return a 0 if no&amp;nbsp;function is set in _callback. So as long as the return value is a C++ arithmetic types, I&amp;#39;ll be good. My mechanism will fail if a developer wants to use functions that return strings, arrays, objects, ...&lt;br /&gt;I think that being able to return any arithmetic type is flexible enough for a generic callback handler.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:7669d1fa-464c-4db9-8e4d-a9e6424bdb32:type=c_cpp&amp;text=template%20%3Ctypename%20R%2C%20typename...%20Args%3E%0A%2F%2F%20restrict%20to%20arithmetic%20data%20types%20for%20return%20value%2C%20or%20void%0A%20%20requires%20std%3A%3Ais_void%3CR%3E%3A%3Avalue%20%7C%7C%20std%3A%3Ais_arithmetic_v%3CR%3E%0Aclass%20Callback%20%7B%0A%0A%2F%2F%20...%0A%0A%09%2F%2A%0A%09%20%2A%20R%20can%20either%20be%20an%20arithmetic%20type%2C%20or%20void%0A%09%20%2A%2F%0A%09inline%20R%20call%28Args...%20args%29%20%7B%0A%09%09if%20constexpr%20%28std%3A%3Ais_void%3CR%3E%3A%3Avalue%29%20%7B%0A%09%09%09if%20%28_callback%20%3D%3D%20nullptr%29%20%7B%0A%09%09%09%09return%3B%0A%09%09%09%7D%0A%09%09%09%28%2A_callback%29%28args...%29%3B%0A%09%09%7D%0A%0A%09%09if%20constexpr%20%28%21%20std%3A%3Ais_void%3CR%3E%3A%3Avalue%29%20%7B%0A%09%09%09if%20%28_callback%20%3D%3D%20nullptr%29%20%7B%0A%09%09%09%09return%200%3B%20%2F%2F%20R%20can%20only%20be%20a%20arithmetic%20type.%200%20should%20work%20as%20default.%0A%09%09%09%7D%0A%09%09%09return%20%28%2A_callback%29%28args...%29%3B%0A%09%09%7D%0A%09%7D%0A%0A%2F%2F%20...]&lt;/p&gt;
&lt;p&gt;I could do nothing. In that case the developer would get a compilation error on this line in my code:&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return 0;&lt;/span&gt;.&amp;nbsp;And they &amp;#39;ll have to go and investigate why my code throws an error.&lt;/p&gt;
&lt;p&gt;C++ now has a mechanism that&amp;#39;s called &lt;a href="https://en.cppreference.com/w/cpp/language/constraints" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;concept&lt;/a&gt;. With that, I can restrict the C++ type that a particular template&amp;nbsp;attribute can have. I will use that to only allow arithmetic types for the return value type R.&lt;br /&gt;When doing that, the compiler will give a clear message, pointing to the user&amp;#39;s code line where they defined an invalid return type:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp;78 |&amp;nbsp; &amp;nbsp; &amp;nbsp;Callback&amp;lt;std::string, const int&amp;amp;, const int&amp;amp;&amp;gt; cb;&lt;br /&gt;error: template constraint failure for &amp;#39;template&amp;lt;class R, class ... Args&amp;gt;&amp;nbsp; requires&amp;nbsp; std::is_arithmetic&amp;lt;_Tp&amp;gt;::value class Callback&amp;#39;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;note: constraints not satisfied&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Thank you for reading. Check&amp;nbsp;&amp;nbsp;[mention:4e1bda4473fd4193bb9be6c83c5309f4:46448885d0e64133bbfbf0cd7b0fd6f7]&amp;nbsp;for yet another dive into hip C++...&lt;/p&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222086?ContentTypeID=1</link><pubDate>Fri, 21 Jun 2024 08:19:08 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:f41bda2f-0f0f-4a6d-968b-369a02db3c93</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222086?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I added the option to use a callback that doesn&amp;#39;t return anything&amp;nbsp;, e.g.:&amp;nbsp; &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;void handler(...)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;First, I allowed the template constraint to accept both arithmetic and void return values.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;template &amp;lt;typename R, typename... Args&amp;gt;
// restrict to arithmetic data types for return value, or void
  requires std::is_void&amp;lt;R&amp;gt;::value || std::is_arithmetic_v&amp;lt;R&amp;gt;
class Callback {&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And altered the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;call()&lt;/span&gt; function in the template, to not return a value if the return type is void:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;	/*
	 * R can either be an arithmetic type, or void
	 */
	inline R call(Args... args) {
		if constexpr (std::is_void&amp;lt;R&amp;gt;::value) {
			if (_callback == nullptr) {
				return;
			}
			(*_callback)(args...);
		}

		if constexpr (! std::is_void&amp;lt;R&amp;gt;::value) {
			if (_callback == nullptr) {
				return 0; // R can only be a arithmetic type. 0 should work as default.
			}
			return (*_callback)(args...);
		}
	}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s an example that uses a bool handler,&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;	// scenario: return a bool
    Callback&amp;lt;bool, const int&amp;amp;, const int&amp;amp;&amp;gt; cb;
    // Use a lambda to execute anonymous C code
    cb.set([](const int&amp;amp; num1, const int&amp;amp; num2) -&amp;gt; bool {
        return num1 == num2;
    });

    printf(&amp;quot;Value: %s\n&amp;quot;, cb.call(a, b) ? &amp;quot;true&amp;quot; : &amp;quot;false&amp;quot;);
	fflush(stdout);
	}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and a void handler:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    // scenario: use void
    Callback&amp;lt;void, const int&amp;amp;, const int&amp;amp;&amp;gt; cb;
    // Use a lambda to execute anonymous C code
    cb.set([](const int&amp;amp; num1, const int&amp;amp; num2) {
        return;
    });
    cb.call(a, b);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;There are more lines of code in the template class definition. But all of that is compile time resolved.&lt;/p&gt;
&lt;p&gt;No executable code is added.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222062?ContentTypeID=1</link><pubDate>Wed, 19 Jun 2024 19:38:06 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:cb32b162-079e-445e-aa2e-db226399e85a</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/222062?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I&amp;#39;ve been testing it with toolchains.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Works with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NXP MCUXpresso&lt;/li&gt;
&lt;li&gt;Pico C/C++ SDK 1.5&lt;/li&gt;
&lt;li&gt;Renesas e2 studio with gcc toolchain (everything, except the optional clause &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;requires std::is_arithmetic&amp;lt;R&amp;gt;::value&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;Eclipse with the arm linux cross-compiler (for Raspberry Pi, BB, ...)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Does not work with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arduino IDE 2.0 avr-gcc: compiler version 7.3 is too low&lt;/li&gt;
&lt;li&gt;Arduino IDE 2.0 arm-gcc: compiler version 7.2 is too low&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222061?ContentTypeID=1</link><pubDate>Wed, 19 Jun 2024 18:14:25 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:7c34c687-05d7-45fa-b7c5-be506f7cdcc0</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222061?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;&amp;nbsp;&lt;a href="https://community.element14.com/members/shabaz"&gt;shabaz&lt;/a&gt;&amp;nbsp;I found where you can set it for Arduino IDE 2.X on windows:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;C:\Users\&lt;em&gt;jancu&lt;/em&gt;\AppData\Local\Arduino15\packages\arduino\hardware\&lt;em&gt;avr\1.8.4&lt;/em&gt;\platform.txt&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You need to&amp;nbsp;replace jancu with your windows user name, and controller family with the board you are working for. And&amp;nbsp;&lt;span&gt;std=gnu++11 with&amp;nbsp;&lt;/span&gt;&lt;strong&gt;std=c++20&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;compiler.&lt;strong&gt;cpp&lt;/strong&gt;.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;edit: I don&amp;#39;t think that this is useful for code that you want to share with others.&lt;br /&gt;edit edit: the setting gets overwritten when updating the IDE&lt;br /&gt;edit edit edit: and avr-gcc 7.x does not support c++20&lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates</title><link>https://community.element14.com/thread/222055?ContentTypeID=1</link><pubDate>Wed, 19 Jun 2024 14:45:12 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:720c6b30-61b4-4ca6-8857-a3cfbb23c918</guid><dc:creator>flyingbean</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/222055?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54719/c-callbacks-and-templates/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Great tip. I could use the template&amp;nbsp; in my projects here.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222034?ContentTypeID=1</link><pubDate>Tue, 18 Jun 2024 19:09:58 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:d620466e-b741-489d-913f-006ea6151215</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222034?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;no, the option is not there&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222030?ContentTypeID=1</link><pubDate>Tue, 18 Jun 2024 19:03:49 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:f6e5827b-3878-45de-9ab9-561ea3296057</guid><dc:creator>shabaz</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/222030?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Ahh thanks for the tip!&amp;nbsp;Simpler to remember than the compile-line option I was using for Pico SDK.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222029?ContentTypeID=1</link><pubDate>Tue, 18 Jun 2024 18:58:05 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:8352efa7-1ba4-4ce0-a51b-bb11b3962a45</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/222029?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;when you press ctl+shift+p in Arduino IDE2, you get a command pallet.&amp;nbsp;There you can set&amp;nbsp; preferences user/workspace (with a form or directly in settings.json)&amp;nbsp;&lt;br /&gt;If the dialect can be set, I&amp;#39;d&amp;nbsp;suspect&amp;nbsp;it&amp;#39;s there ...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222023?ContentTypeID=1</link><pubDate>Tue, 18 Jun 2024 15:51:28 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:ed53081e-9871-419b-bc43-99ced99bebf6</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/222023?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;for pico C sdk:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" style="max-height:93px;max-width:354px;" height="93" src="https://community.element14.com/resized-image/__size/708x186/__key/communityserver-discussions-components-files/126/pastedimage1718724853161v1.png" width="354"  /&gt;&lt;/p&gt;
&lt;p&gt;for eclipse:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" alt="image" style="max-height:256px;max-width:415px;" height="256" src="https://community.element14.com/resized-image/__size/830x512/__key/communityserver-discussions-components-files/126/pastedimage1718725393112v2.png" width="415"  /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;No idea how to set in Arduino&amp;nbsp;IDE V2. V1 had a platform file, that you could edit.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ and templates: restrict what types can be used in a template</title><link>https://community.element14.com/thread/222022?ContentTypeID=1</link><pubDate>Tue, 18 Jun 2024 15:07:23 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:3724bf7c-db32-4fb6-a6fa-ecec3eb54451</guid><dc:creator>shabaz</dc:creator><slash:comments>2</slash:comments><comments>https://community.element14.com/thread/222022?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54725/c-and-templates-restrict-what-types-can-be-used-in-a-template/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Very interesting!&lt;/p&gt;
&lt;p&gt;If using g++ to build it, I correctly see the following:&lt;/p&gt;
&lt;pre&gt;error: &amp;#39;requires&amp;#39; does not name a type&lt;br /&gt;&amp;nbsp; requires std::is_arithmetic&amp;lt;R&amp;gt;::value&lt;br /&gt;&lt;br /&gt;note: &amp;#39;requires&amp;#39; only available with &amp;#39;&lt;strong&gt;-std=c++20&lt;/strong&gt;&amp;#39; or &amp;#39;-fconcepts&amp;#39;&lt;/pre&gt;
&lt;p&gt;All is fine, of course, when I add the specified switch.&lt;/p&gt;
&lt;p&gt;However, Arduino IDE is a bit vague:&lt;/p&gt;
&lt;pre&gt;error: &amp;#39;requires&amp;#39; does not name a type&lt;br /&gt; requires std::is_arithmetic&amp;lt;R&amp;gt;::value&lt;br /&gt; ^~~~~~~~&lt;br /&gt;&lt;br /&gt;exit status 1&lt;br /&gt;&lt;br /&gt;Compilation error: &amp;#39;requires&amp;#39; does not name a type&lt;/pre&gt;
&lt;p&gt;It fails to mention that the reason is the switch is missing. A pity the&amp;nbsp;IDE doesn&amp;#39;t support it, because this sort of feature is excellent for real-time applications, and would be a nice way to demonstrate. Still, at least Pico can build with it (using&amp;nbsp;-std=c++20 in the COMPILE_OPTIONS in CMakeLists.txt&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: C++ callbacks and templates: make the Callback class call an object member, a static member, a C function and a pure lambda function</title><link>https://community.element14.com/thread/221997?ContentTypeID=1</link><pubDate>Sun, 16 Jun 2024 17:02:24 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:91971724-ebe4-49fb-9803-86f40955a46a</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>0</slash:comments><comments>https://community.element14.com/thread/221997?ContentTypeID=1</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54721/c-callbacks-and-templates-make-the-callback-class-call-an-object-member-a-static-member-a-c-function-and-a-pure-lambda-function/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Example program for a Pico:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a Led object knows how to toggle&lt;/li&gt;
&lt;li&gt;the toggle method is set as callback&amp;nbsp;&lt;/li&gt;
&lt;li&gt;when a rising edge interrupt occurs on GPIO 27 (where a button is attached), the callback is called.&lt;br /&gt;The usual bounce happens if you don&amp;#39;t filter the signal, but for a demo it will do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;pico/stdlib.h&amp;quot;
#include &amp;quot;hardware/gpio.h&amp;quot;

#include &amp;lt;cstdio&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;quot;callbackmanager.h&amp;quot;

// button on pico eurocard
#define BUTTON (27)

class Led {
public:
      void init() {
        gpio_init(PICO_DEFAULT_LED_PIN);
        gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
      }
      int toggle() {
        // toggle a led, then exit
        gpio_put(PICO_DEFAULT_LED_PIN, !gpio_get(PICO_DEFAULT_LED_PIN));
        return 0;
      }
};

Callback&amp;lt;int&amp;gt; cb_button;
Led led;

/*
handle SDK HAL gpio callback.
hand over to the Callback object
*/
void gpio_hal_callback(uint gpio, uint32_t events) {
  if((gpio == BUTTON) &amp;amp;&amp;amp; ((events &amp;amp; GPIO_IRQ_EDGE_RISE))) {
      // HAL reports we received a rising edge from the button
      // invoke callback
      cb_button.call();
  }
}

int main() {
    stdio_init_all();
    gpio_init(BUTTON);
    gpio_set_dir(BUTTON, GPIO_IN);
    gpio_set_pulls(BUTTON, true, false);

    led.init();

    cb_button.set([]() -&amp;gt; int {
        return led.toggle();
    });

    // enable SDK HAL interrupt for gpio
    gpio_set_irq_enabled_with_callback(BUTTON, GPIO_IRQ_EDGE_RISE, true, &amp;amp;gpio_hal_callback);

    while(true) {}
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In this example, you see 2 variations on the previous examples:&lt;/p&gt;
&lt;p&gt;- the Callback template can also be used&amp;nbsp;with 0 attributes.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;code&gt;&lt;span&gt;Callback&lt;/span&gt;&lt;span&gt;&amp;lt;int&amp;gt; &lt;/span&gt;&lt;span&gt;cb_button&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case, the&amp;nbsp;class will only allow that you set handlers that take no arguments (the int is the return value type).&lt;/p&gt;
&lt;p&gt;- I did not put anything in between the lambda &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;[]&lt;/span&gt;. Because&amp;nbsp;the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;cb_button&lt;/span&gt; object is a global object. You don&amp;#39;t have to capture&amp;nbsp;global objects, because lambdas (like any code in your program)&amp;nbsp;can access&amp;nbsp;them. (It actually generates a compile warning if you try to capture a global variable for a lambda:&amp;nbsp;&lt;span&gt;capture of variable &amp;#39;cb_button&amp;#39; with non-automatic storage duration&lt;/span&gt;). &lt;br /&gt;I&amp;#39;m deliberately simplifying the explanation here by calling this a global instead of&amp;nbsp;&lt;span&gt;variable with non-automatic storage. But I guess that if you know what non-automatic storage duration is, you&amp;nbsp;don&amp;#39;t need my explanation anyway&amp;nbsp;&lt;span class="emoticon" data-url="https://community.element14.com/cfs-file/__key/system/emoji/1f642.svg" title="Slight smile"&gt;&amp;#x1f642;&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>C++ callbacks and templates: make the Callback class call an object member, a static member, a C function and a pure lambda function</title><link>https://community.element14.com/thread/54721?ContentTypeID=0</link><pubDate>Sun, 16 Jun 2024 10:25:57 GMT</pubDate><guid isPermaLink="false">93d5dcb4-84c2-446f-b2cb-99731719e767:5b356e06-5881-4266-b1c9-4f99fba9084c</guid><dc:creator>Jan Cumps</dc:creator><slash:comments>1</slash:comments><comments>https://community.element14.com/thread/54721?ContentTypeID=0</comments><wfw:commentRss>https://community.element14.com/products/devtools/software/f/forum/54721/c-callbacks-and-templates-make-the-callback-class-call-an-object-member-a-static-member-a-c-function-and-a-pure-lambda-function/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;I developed a templated C++ callback manager:&amp;nbsp;&amp;nbsp;[mention:95e9f4be67c8415a81cfd67f3fd1ce81:46448885d0e64133bbfbf0cd7b0fd6f7]&amp;nbsp;.&amp;nbsp;I claimed that it&amp;nbsp;can&amp;nbsp;call back&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;a classic C function, &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;a lambda, &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;a static class method or &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;an object method,&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;and it supports these return types:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span&gt;void&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;bool&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;number&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;objects (if the class has a default constructor and &amp;quot;is returnable&amp;quot;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;But in that first post, I only showed an example where the method of an object was used as callback handler.&amp;nbsp;In this post, I show all 4 scenarios.&amp;nbsp;This time,&amp;nbsp;I&amp;#39;m not showing the power of templates, but the power of lambda functions.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As a refresher, here is the Callback manager. Unchanged since previous post. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jancumps/callbackmanager/blob/main/callbackmanager.cpp" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;callmanager.cpp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:be901033-936a-48f0-b321-2194d965624d:type=csharp&amp;text=module%3B%0D%0A%0D%0A%23include%20%3Cconcepts%3E%0D%0A%23include%20%3Cfunctional%3E%0D%0A%0D%0Aexport%20module%20callbackmanager%3B%0D%0A%0D%0Anamespace%20callbackmanager%20%7B%0D%0A%0D%0A%2F%2F%20concept%20guards%20what%20types%20of%20return%20values%20we%20can%20handle%0D%0Atemplate%3Ctypename%20R%3E%0D%0Aconcept%20Callbackable%20%3D%20%0D%0A%09std%3A%3Ais_void%3CR%3E%3A%3Avalue%20%7C%7C%0D%0A%09std%3A%3Ais_arithmetic_v%3CR%3E%20%7C%7C%0D%0A%09std%3A%3Ais_class_v%3CR%3E%3B%0D%0A%0D%0Aexport%20template%20%3CCallbackable%20R%2C%20typename...%20Args%3E%0D%0Aclass%20Callback%20%7B%0D%0A%09using%20callbackfunction_t%20%3D%20std%3A%3Afunction%3CR%28Args...%29%3E%3B%09%0D%0Apublic%3A%0D%0A%09Callback%28%29%20%3A%20callback_%28nullptr%29%2C%20is_callback_set%28false%29%7B%7D%0D%0A%0D%0A%09inline%20void%20set%28callbackfunction_t%20callback%29%20%7B%0D%0A%09%20%20%20%20callback_%20%3D%20callback%3B%0D%0A%09%09is_callback_set%20%3D%20true%3B%0D%0A%09%7D%0D%0A%0D%0A%09inline%20void%20unset%28%29%20%7B%0D%0A%09%09callback_%20%3D%20nullptr%3B%0D%0A%09%09is_callback_set%20%3D%20false%3B%0D%0A%09%7D%0D%0A%0D%0A%09%5B%5Bdeprecated%28%22Use%20operator%20%28%29%20instead.%22%29%5D%5D%0D%0A%09inline%20R%20call%28Args...%20args%29%20%7B%0D%0A%09%09return%20%2Athis%28args...%29%3B%0D%0A%09%7D%0D%0A%0D%0A%09inline%20bool%20is_set%28%29%20%7B%0D%0A%09%09return%20is_callback_set%3B%09%09%0D%0A%09%7D%0D%0A%0D%0A%09%2F%2A%0D%0A%09%20%2A%20R%20can%20be%20an%20arithmetic%20type%2C%20an%20object%2C%20or%20void%0D%0A%09%20%2A%2F%0D%0A%09inline%20R%20operator%28%29%28Args...%20args%29%20%7B%0D%0A%09%09if%20constexpr%20%28std%3A%3Ais_void%3CR%3E%3A%3Avalue%29%20%7B%20%20%2F%2F%20void%0D%0A%09%09%09if%20%28%21is_callback_set%29%20%7B%0D%0A%09%09%09%09return%3B%0D%0A%09%09%09%7D%20else%20%7B%0D%0A%09%09%09%09%28callback_%29%28args...%29%3B%0D%0A%09%09%09%7D%0D%0A%09%09%7D%20else%20if%20constexpr%20%28std%3A%3Ais_class%3CR%3E%3A%3Avalue%29%20%7B%20%2F%2F%20object%0D%0A%09%09%09if%20%28%21is_callback_set%29%20%7B%0D%0A%09%09%09%09return%20R%28%29%3B%0D%0A%09%09%09%7D%20else%20%7B%0D%0A%09%09%09%09return%20%28callback_%29%28args...%29%3B%0D%0A%09%09%09%7D%0D%0A%09%09%7D%20else%20%7B%20%2F%2F%20not%20void%20nor%20object%0D%0A%09%09%09if%20%28%21is_callback_set%29%20%7B%0D%0A%09%09%09%09return%200%3B%20%2F%2F%20R%20can%20only%20be%20a%20arithmetic%20type.%200%20should%20work%20as%20default.%0D%0A%09%09%09%7D%20else%20%7B%0D%0A%09%09%09%09return%20%28callback_%29%28args...%29%3B%0D%0A%09%09%09%7D%0D%0A%09%09%7D%0D%0A%09%7D%0D%0A%0D%0Aprivate%3A%0D%0A%09callbackfunction_t%20callback_%3B%0D%0A%09bool%20is_callback_set%3B%0D%0A%7D%3B%0D%0A%0D%0A%7D%20%2F%2F%20namespace%20callbackmanager]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;And here is the code that exercises the 4 scenarios. Each scenario is&amp;nbsp;surrounded by {}. That means that they run in their own little isolated scope, And they don&amp;#39;t spoil each other.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;First, some code that will be used in the test. They are 3 different types of functions / methods:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family:inherit;"&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;MyClass&lt;/span&gt;, now with a static and normal member function. So that we can test a scenario where we call an object member, and a scenario where we call a static class member.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family:inherit;"&gt;classic C function&amp;nbsp;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;functionHandler()&lt;/span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style="font-family:inherit;"&gt;All 3 do the same thing. They return the sum of two integers.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:67e10ab6-e502-474d-9c80-fb99b641b071:type=c_cpp&amp;text=%23include%20%3Ccstdio%3E%0A%23include%20%3Cstring%3E%0A%23include%20%3Ctypeinfo%3E%0A%0Aimport%20callbackmanager%3B%0A%0Aclass%20MyClass%20%7B%0Apublic%3A%0A%20%20%20%20%20%20inline%20int%20handler%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20const%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20static%20inline%20int%20staticHandler%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0A%20%20%20%20%20%20%7D%0A%7D%3B%0A%0Aint%20functionHandler%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0A%20%20%20%20return%20num1%20%2B%20num2%3B%0A%7D]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Then the 4 tests:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:246a6207-76fd-41a4-a42a-67202d3f1478:type=c_cpp&amp;text=int%20main%28%29%20%7B%0A%0A%20%20%20%20int%20a%20%3D%204%3B%0A%20%20%20%20int%20b%20%3D%205%3B%0A%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20capture%20myClass%20and%20call%20the%20object%20method%0A%20%20%20%20cb.set%28%5B%26myClass%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20myClass.handler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%20%2F%2F%20We%20might%20be%20on%20an%20embedded%20system%2C%20use%20printf%28%29%20and%20not%20std%3A%3Acout%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20static%20method%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20call%20the%20static%20method%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20MyClass%3A%3AstaticHandler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%20%2F%2F%20We%20might%20be%20on%20an%20embedded%20system%2C%20use%20printf%28%29%20and%20not%20std%3A%3Acout%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20C%20function%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20call%20the%20classic%20C%20function%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20functionHandler%28num1%2C%20num2%29%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%3D%20cb%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%20%2F%2F%20We%20might%20be%20on%20an%20embedded%20system%2C%20use%20printf%28%29%20and%20not%20std%3A%3Acout%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20call%20pure%20lambda%0A%20%20%20%20Callback%3Cint%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20num1%20%2B%20num2%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20int%20o%20%20%3D%20cb%28a%2C%20b%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25i%5Cn%22%2C%20o%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20return%20a%20bool%0A%20%20%20%20Callback%3Cbool%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20-%3E%20bool%20%7B%0A%20%20%20%20%20%20%20%20return%20num1%20%3D%3D%20num2%3B%0A%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20printf%28%22Value%3A%20%25s%5Cn%22%2C%20cb%28a%2C%20b%29%20%3F%20%22true%22%20%3A%20%22false%22%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%7B%20%2F%2F%20scenario%3A%20use%20void%0A%20%20%20%20Callback%3Cvoid%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0A%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%29%3B%0A%20%20%20%20cb%28a%2C%20b%29%3B%0A%09%7D%0A%09%0A%20%20%20%20%7B%20%2F%2F%20scenario%3A%20return%20an%20object%0A%20%20%20%20class%20return_class%20%7B%0A%20%20%20%20public%3A%0A%20%20%20%20%20%20%20%20return_class%28%29%20%3A%20value_%280%29%20%7B%7D%3B%0A%20%20%20%20%20%20%20%20int%20value_%3B%0A%20%20%20%20%7D%3B%0A%0A%09callbackmanager%3A%3ACallback%3Creturn_class%3E%20cb%3B%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0A%20%20%20%20cb.set%28%5B%5D%28%29%20-%3E%20return_class%20%7B%0A%20%20%20%20%20%20%20%20return_class%20rc%3B%0A%20%20%20%20%20%20%20%20rc.value_%20%3D%201%3B%0A%20%20%20%20%20%20%20%20return%20rc%3B%0A%20%20%20%20%7D%29%3B%0A%20%20%20%20return_class%20ret%20%3D%20cb%28%29%3B%0A%20%20%20%20printf%28%22Value%3A%20%25d%5Cn%22%2C%20ret.value_%20%29%3B%0A%09fflush%28stdout%29%3B%0A%09%7D%0A%0A%09%2F%2A%0A%09%7B%20%2F%2F%20scenario%3A%20use%20an%20unsupported%20%28non-fundamental%29%20type%20for%20return%20value%20R%0A%09%20%20%2F%2F%20this%20will%20generate%20a%20compile%20error%0A%20%20%20%20Callback%3Cstd%3A%3Astring%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0A%09%7D%0A%7D]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;edit:&amp;nbsp;The template also allows void return values. Some more tests:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;[embed:dc8ab71f-3b98-42d9-b0f6-e21e02a0f8e2:313ac996-b26f-41fa-bcc9-ff3275812ccb:type=c_cpp&amp;text=%09%7B%20%2F%2F%20scenario%3A%20use%20void%0D%0A%20%20%20%20Callback%3Cvoid%2C%20const%20int%26%2C%20const%20int%26%3E%20cb%3B%0D%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0D%0A%20%20%20%20cb.set%28%5B%5D%28const%20int%26%20num1%2C%20const%20int%26%20num2%29%20%7B%0D%0A%20%20%20%20%20%20%20%20printf%28%22void%20gets%20num1%3A%20%25i%2C%20num2%3A%20%25i%5Cn%22%2C%20num1%2C%20num2%29%3B%0D%0A%20%20%20%20%09fflush%28stdout%29%3B%0D%0A%20%20%20%20%20%20%20%20return%3B%0D%0A%20%20%20%20%7D%29%3B%0D%0A%20%20%20%20cb.call%28a%2C%20b%29%3B%0D%0A%09%7D%0D%0A%0D%0A%09%7B%20%2F%2F%20scenario%3A%20use%20void%2C%20and%20no%20attributes%0D%0A%20%20%20%20Callback%3Cvoid%3E%20cb%3B%0D%0A%20%20%20%20%2F%2F%20Use%20a%20lambda%20to%20execute%20anonymous%20C%20code%0D%0A%20%20%20%20cb.set%28%5B%5D%28%29%20%7B%0D%0A%20%20%20%20%20%20%20%20printf%28%22void%20with%20no%20parameters%5Cn%22%29%3B%0D%0A%20%20%20%20%09fflush%28stdout%29%3B%0D%0A%20%20%20%20%20%20%20%20return%3B%0D%0A%20%20%20%20%7D%29%3B%0D%0A%20%20%20%20cb.call%28%29%3B%0D%0A%09%7D]&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Scenarios, in order of execution: (&lt;em&gt;edit: this was written before I revised the code to support&amp;nbsp;configurable return value. The test code above is adapted, but I didn&amp;#39;t change the images below)&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span&gt;call object method&lt;br /&gt;In this one, I create object &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;myClass&lt;/span&gt; of type &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;MyClass&lt;/span&gt;. Then pass its &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;handle()&lt;/span&gt; method as callback. &lt;br /&gt;This was the scenario of the first post.&lt;br /&gt;&lt;img style="max-height:360px;max-width:640px;" alt=" " src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/pastedimage1718533908601v1.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;call static class method&lt;br /&gt;In this test, I don&amp;#39;t declare an object of type MyClass. I pass the static &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;MyClass::staticHandle()&lt;br /&gt;&lt;img style="max-height:360px;max-width:640px;" alt=" " src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/pastedimage1718533940203v2.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;classic C function&lt;br /&gt;Here, the callback gets a very common C function, named &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;functionHandler()&lt;/span&gt;, as handler.&amp;nbsp;&lt;br /&gt;&lt;img style="max-height:360px;max-width:640px;" alt=" " src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/pastedimage1718533971892v3.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;a pure lambda.&lt;br /&gt;In this test, I pass an anonymous block of code as handler:&lt;br /&gt;&lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;return num1 + num2;&lt;/span&gt;&lt;br /&gt;&lt;img style="max-height:360px;max-width:640px;" alt=" " src="https://community.element14.com/resized-image/__size/1280x720/__key/communityserver-discussions-components-files/126/pastedimage1718533988796v4.png" /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;return an object. This is added on 09-mar-2025.Works as long as the object supports a default constructor and does not forbid copy / assign.&lt;br /&gt;&lt;img style="max-height:287px;max-width:367px;" alt=" " height="287" src="https://community.element14.com/resized-image/__size/734x574/__key/communityserver-discussions-components-files/126/pastedimage1741524650836v1.png" width="367" /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In each test,&amp;nbsp;the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;Callback&lt;/span&gt; object &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;cb&lt;/span&gt; will call the code that&amp;#39;s given to it in the &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;set()&lt;/span&gt; call. All using the exact same little Callback template class. If you would set breakpoints, here is where the code would stop for each of the 4 cases:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img style="max-height:678px;max-width:499px;" alt=" " height="678" src="https://community.element14.com/resized-image/__size/998x1356/__key/communityserver-discussions-components-files/126/pastedimage1718535291980v1.png" width="499" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:75%;"&gt;&lt;em&gt;edit: this was written before I replaced call() by operator ()..In your code, don&amp;#39;t use &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;cb.call(args)&lt;/span&gt;, but &lt;span style="font-family:&amp;#39;courier new&amp;#39;, courier;"&gt;cb(args)&lt;/span&gt;. The test code&amp;nbsp;in the blog is adapted, but I didn&amp;#39;t change the images.&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;The test code is &lt;a href="https://gist.github.com/jancumps/6dbc257c80911270775ee9d44a5131ee" rel="noopener noreferrer nofollow" target="_blank" data-e14adj="t"&gt;available as a Gist&lt;/a&gt;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description></item></channel></rss>