<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: aodinokov</title>
    <description>The latest articles on DEV Community by aodinokov (@alexey_odinokov_734a1ba32).</description>
    <link>https://dev.to/alexey_odinokov_734a1ba32</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1536846%2Fb12b5dbd-7b31-4946-8413-fb7e6975a377.png</url>
      <title>DEV Community: aodinokov</title>
      <link>https://dev.to/alexey_odinokov_734a1ba32</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexey_odinokov_734a1ba32"/>
    <language>en</language>
    <item>
      <title>C Reflection Magic: Simple Logging with A Wrapper for Printing Arbitrary Functions Arguments and Results</title>
      <dc:creator>aodinokov</dc:creator>
      <pubDate>Thu, 06 Jun 2024 13:51:04 +0000</pubDate>
      <link>https://dev.to/alexey_odinokov_734a1ba32/c-reflection-magic-a-wrapper-for-printing-arbitrary-functions-arguments-and-results-1k0b</link>
      <guid>https://dev.to/alexey_odinokov_734a1ba32/c-reflection-magic-a-wrapper-for-printing-arbitrary-functions-arguments-and-results-1k0b</guid>
      <description>&lt;p&gt;&lt;em&gt;This article is a research report which covers some potential implementation aspects of writing a helper wrapper which will automatically log arguments and results of the arbitrary C function. This is one of the examples why reflection may be useful even in C. The implementation is based on the &lt;a href="https://github.com/aodinokov/metac"&gt;Metac&lt;/a&gt; project. The introduction of it was given in &lt;a href="https://dev.to/alexey_odinokov_734a1ba32/c-self-reflection-or-when-the-good-old-dwarf-makes-your-elves-face-their-unconscious-truth-5367"&gt;this article&lt;/a&gt;. The research has some good results, but it still in progress. The comments on how it could be done in a better way are appreciated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Logging is one of the important ways of debugging. Making proper logging is a key to understanding what potentially went wrong without using a debugger. But it’s annoying to print out all the arguments of each function and its result. C reflection with Metac could potentially have an ability to do this, because debugging information provided by DWARF has all the data about the type of each argument. Check it out. Here is the testing application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdarg.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"metac/reflect.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;test_function1_with_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;METAC_GSYM_LINK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_function1_with_args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fn returned: %i&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_function1_with_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to make some kind of wrapper to print arguments of &lt;code&gt;test_function1_with_args&lt;/code&gt;. Metac will generate its reflection info since &lt;code&gt;METAC_GSYM_LINK(test_function1_with_args);&lt;/code&gt; is in the code. For simplicity int and short argument types are selected. The first idea how we could create a wrapper is - create a macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// use va_args and debug information about types to print value of each argument&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;#define METAC_WRAP_FN(_fn_, _args_...) ({ \
        print_args(METAC_GSYM_LINK_ENTRY(_fn_), _args_); \
        _fn_(_args_); \
    })
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// use wrapper instead of printf("fn returned: %i\n", test_function1_with_args(1, 2));&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fn returned: %i&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;METAC_WRAP_FN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_function1_with_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wrapper so far handles only arguments, but it’s ok for the first step. Lets try to implement print_args. Here is the first naive attempt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;metac_entry_has_paremeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;va_list&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;va_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s("&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metac_entry_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// output each argument&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;metac_entry_paremeter_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// get i-th arg&lt;/span&gt;
        &lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_param_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_by_paremeter_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_is_parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// something is wrong&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// if it’s … argument just print … - there is no way so far to handle that&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_is_unspecified_parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// we don't support printing va_args... there is no generic way&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// get arg name and info about arg type&lt;/span&gt;
        &lt;span class="n"&gt;metac_name_t&lt;/span&gt; &lt;span class="n"&gt;param_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_param_type_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_parameter_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;param_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// something is wrong&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// lets handle only base_types for now&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_is_base_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_type_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// take what type of base type it is. It can be char, unsigned char.. etc&lt;/span&gt;
            &lt;span class="n"&gt;metac_name_t&lt;/span&gt; &lt;span class="n"&gt;param_base_type_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_base_type_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_type_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// if _type_ is matching with param_base_type_name, get data using va_arg and print it.&lt;/span&gt;
&lt;span class="cp"&gt;#define _base_type_arg_(_type_, _pseudoname_) \
    do { \
        if (strcmp(param_base_type_name, #_pseudoname_) == 0) { \
            _type_ val = va_arg(args, _type_); \
            metac_value_t * p_val = metac_new_value(p_param_type_entry, &amp;amp;val); \
            if (p_val == NULL) { \
                break; \
            } \
            char * s = metac_value_string(p_val); \
            if (s == NULL) { \
                metac_value_delete(p_val); \
                break; \
            } \
            printf("%s: %s", param_name, s); \
            free(s); \
            metac_value_delete(p_val); \
        } \
    } while(0)
&lt;/span&gt;    &lt;span class="c1"&gt;// handle all known base types&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;short&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;_Bool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_base_type_arg_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;complex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;#undef _base_type_arg_
&lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;")&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;va_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we run it we will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% ./c_print_args
test_function1_with_args&lt;span class="o"&gt;(&lt;/span&gt;a: 1, b: 2&lt;span class="o"&gt;)&lt;/span&gt;
fn returned: 9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works! But it handles only base types. And we want it to be universal.&lt;/p&gt;

&lt;p&gt;The main challenge here is with this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt; &lt;span class="n"&gt;_type_&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;va_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_type_&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;C's &lt;code&gt;va_arg&lt;/code&gt; macro requires the type of the argument to be known at compile time. However, reflection information only provides type names at runtime. Can we trick it? &lt;code&gt;va_arg&lt;/code&gt; is a macros which covers a builtin function. The second parameter is a type (very non-typical thing). But why does this thing at all needs the type? The answer is - to understand the size and to be able to take it from the stack. We need to cover all possible sizes and to get a pointer to the next argument. On Metac side we know the size of argument - we can use this snippet to get it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;        &lt;span class="n"&gt;metac_size_t&lt;/span&gt; &lt;span class="n"&gt;param_byte_sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_byte_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_type_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;param_byte_sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// something is wrong&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a next idea let's make the macro which will cover 1 size and make sure that we handle it properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;handled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#define _handle_sz_(_sz_) \
        do { \
            if (param_byte_sz == _sz_) { \
                char *x = va_arg(args, char[_sz_]); \
                memcpy(buf, x, _sz_); \
                handled = 1; \
            } \
        } while(0)
&lt;/span&gt;        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// and so on ...&lt;/span&gt;
        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;#undef _handle_sz_
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this approach we covered different sizes from 1 to 32. We could generate a code and cover arguments sized till any arbitrary number, but in most cases people use pointers rather than passing arrays/structures directly. For the sake of our example we’ll keep 32.&lt;br&gt;
Lets refactor our function to make it more reusable split it into 2 &lt;code&gt;vprint_args&lt;/code&gt; and &lt;code&gt;print_args&lt;/code&gt; similarly to ‘vprtintf’ and &lt;code&gt;printf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;vprint_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_tag_map_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_tag_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;va_list&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;metac_entry_has_paremeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s("&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metac_entry_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;metac_entry_paremeter_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_param_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_by_paremeter_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_is_parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// something is wrong&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_is_unspecified_parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// we don't support printing va_args... there is no generic way&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;metac_name_t&lt;/span&gt; &lt;span class="n"&gt;param_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_param_type_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_parameter_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;p_param_type_entry&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// something is wrong&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;metac_size_t&lt;/span&gt; &lt;span class="n"&gt;param_byte_sz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_entry_byte_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_type_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;param_byte_sz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// something is wrong&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;handled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#define _handle_sz_(_sz_) \
        do { \
            if (param_byte_sz == _sz_) { \
                char *x = va_arg(args, char[_sz_]); \
                memcpy(buf, x, _sz_); \
                handled = 1; \
            } \
        } while(0)
&lt;/span&gt;        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
        &lt;span class="n"&gt;_handle_sz_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;#undef _handle_sz_
&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handled&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;metac_value_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_new_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_type_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_value_string_ex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;METAC_WMODE_deep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_tag_map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;metac_value_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;arg_decl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_param_type_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg_decl&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;metac_value_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg_decl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" = %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg_decl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;metac_value_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_tag_map_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_tag_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metac_entry_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;va_list&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;va_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vprint_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_tag_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;va_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reader may notice that we added &lt;code&gt;p_tag_map&lt;/code&gt; as the first argument. This is for the further research - it's not used in this article.&lt;/p&gt;

&lt;p&gt;Lets now try to create a part which handles the result. Unfortunately &lt;a href="https://en.cppreference.com/w/c/language/typeof"&gt;typeof&lt;/a&gt; isn’t supported till C23 (&lt;a href="https://gcc.gnu.org/onlinedocs/gcc/Typeof.html"&gt;gcc extension&lt;/a&gt; as an option, but it won't work with clang) and we have a dilemma - do we want to keep our &lt;code&gt;METAC_WRAP_FN&lt;/code&gt; notation as is, or it’s ok to pass it one more argument - type of the function result to be used as a buffer. Probably we could use &lt;code&gt;libffi&lt;/code&gt; to handle this in a universal way - Metac knows the type, but it’s not clear how to put the returned data into the buffer of the proper size. For simplicity let’s change our macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define METAC_WRAP_FN_RES(_type_, _fn_, _args_...) ({ \
        printf("calling "); \
        print_args(NULL, METAC_GSYM_LINK_ENTRY(_fn_), _args_); \
        printf("\n"); \
        WITH_METAC_DECLLOC(loc, _type_ res = _fn_(_args_)); \
        print_args_and_res(NULL, METAC_GSYM_LINK_ENTRY(_fn_), METAC_VALUE_FROM_DECLLOC(loc, res), _args_); \
        res; \
    })
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’re passing &lt;code&gt;_type_&lt;/code&gt; as a first argument to store the result. If we pass incorrect &lt;em&gt;type&lt;/em&gt; or arguments - the compiler will complain about this &lt;code&gt;_type_ res = _fn_(_args_)&lt;/code&gt;. This is good.&lt;br&gt;
Printing out the result is a trivial task, we already did that in the first article. Let’s also update our test functions to accept some different types of parameters.&lt;br&gt;
&lt;a href="https://github.com/aodinokov/metac/tree/dc984d445070c8a037f7aa8e14536cc8c865c433/examples/c_print_args"&gt;Here&lt;/a&gt; is the final example code.&lt;/p&gt;

&lt;p&gt;If we run it we’ll get with the comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% ./c_print_args

&lt;span class="c"&gt;# show args of base type arg function&lt;/span&gt;
calling test_function1_with_args&lt;span class="o"&gt;(&lt;/span&gt;int a &lt;span class="o"&gt;=&lt;/span&gt; 10, short int b &lt;span class="o"&gt;=&lt;/span&gt; 22&lt;span class="o"&gt;)&lt;/span&gt;
fn returned: 38

&lt;span class="c"&gt;# show args if the first arg is a pointer&lt;/span&gt;
calling test_function2_with_args&lt;span class="o"&gt;(&lt;/span&gt;int &lt;span class="k"&gt;*&lt;/span&gt; a &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;int &lt;span class="o"&gt;[]){&lt;/span&gt;689,&lt;span class="o"&gt;}&lt;/span&gt;, short int b &lt;span class="o"&gt;=&lt;/span&gt; 22&lt;span class="o"&gt;)&lt;/span&gt;
fn returned: 1710

&lt;span class="c"&gt;# using METAC_WRAP_FN_RES which will print the result. using pointer to list&lt;/span&gt;
calling test_function3_with_args&lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="k"&gt;*&lt;/span&gt; p_list &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 42.420000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;struct list_s &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 45.400000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; NULL,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;})&lt;/span&gt;
fn returned: 87.820000

&lt;span class="c"&gt;# another example of METAC_WRAP_FN_RES with int * as a first arg&lt;/span&gt;
calling test_function2_with_args&lt;span class="o"&gt;(&lt;/span&gt;int &lt;span class="k"&gt;*&lt;/span&gt; a &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;int &lt;span class="o"&gt;[]){&lt;/span&gt;689,&lt;span class="o"&gt;}&lt;/span&gt;, short int b &lt;span class="o"&gt;=&lt;/span&gt; 22&lt;span class="o"&gt;)&lt;/span&gt;
test_function2_with_args&lt;span class="o"&gt;(&lt;/span&gt;int &lt;span class="k"&gt;*&lt;/span&gt; a &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;int &lt;span class="o"&gt;[]){&lt;/span&gt;689,&lt;span class="o"&gt;}&lt;/span&gt;, short int b &lt;span class="o"&gt;=&lt;/span&gt; 22&lt;span class="o"&gt;)&lt;/span&gt; returned 1710

&lt;span class="c"&gt;# the log where 1 func with wrapper calls another func with wrapper&lt;/span&gt;
calling test_function4_with_args&lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="k"&gt;*&lt;/span&gt; p_list &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 42.420000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;struct list_s &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 45.400000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; NULL,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;})&lt;/span&gt;
calling test_function3_with_args&lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="k"&gt;*&lt;/span&gt; p_list &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 42.420000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;struct list_s &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 45.400000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; NULL,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;})&lt;/span&gt;
test_function3_with_args&lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="k"&gt;*&lt;/span&gt; p_list &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 42.420000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;struct list_s &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 45.400000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; NULL,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;})&lt;/span&gt; returned 87.820000
test_function4_with_args&lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="k"&gt;*&lt;/span&gt; p_list &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;list_t &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 42.420000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;struct list_s &lt;span class="o"&gt;[]){{&lt;/span&gt;.x &lt;span class="o"&gt;=&lt;/span&gt; 45.400000, .p_next &lt;span class="o"&gt;=&lt;/span&gt; NULL,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;}&lt;/span&gt;,&lt;span class="o"&gt;})&lt;/span&gt; returned &lt;span class="nt"&gt;-912&lt;/span&gt;.180000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s seen that Metac prints for us the &lt;code&gt;deep&lt;/code&gt; representation of the arguments as well as results. In general it works, though there are some flaws like a need to handle each size of argument separately.&lt;/p&gt;

&lt;p&gt;Here are some additional limitations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;clang doesn't expose debug information about external functions like &lt;code&gt;printf&lt;/code&gt;. That means - our wrapper won't work with that as-is. We may need to introduce some additional tricks.&lt;/li&gt;
&lt;li&gt;functions with unspecified arguments &lt;code&gt;...&lt;/code&gt; won't show such arguments. there is no generic way, but potentially we may want to give a way to provide a callback to extract information for such cases.&lt;/li&gt;
&lt;li&gt;there is no (yet?) support for the cases of linked arguments, e.g. when we pass pointer and length as 2 separate but logically connected arguments .&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have any suggestion on how it could be more generic - please comment. Thanks for reading!&lt;/p&gt;

</description>
      <category>c</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
    <item>
      <title>C Reflection: When the Good Old DWARF Makes Your Elves Face Their Unconscious Truth</title>
      <dc:creator>aodinokov</dc:creator>
      <pubDate>Thu, 30 May 2024 18:29:12 +0000</pubDate>
      <link>https://dev.to/alexey_odinokov_734a1ba32/c-self-reflection-or-when-the-good-old-dwarf-makes-your-elves-face-their-unconscious-truth-5367</link>
      <guid>https://dev.to/alexey_odinokov_734a1ba32/c-self-reflection-or-when-the-good-old-dwarf-makes-your-elves-face-their-unconscious-truth-5367</guid>
      <description>&lt;p&gt;&lt;em&gt;The article is dedicated to the ability of major compilers like gcc or clang to be a source for reflection information for C applications, which makes possible C reflection implementation like &lt;a href="https://github.com/aodinokov/metac"&gt;Metac&lt;/a&gt;. This works for elf, macho and pe formats on the corresponding platforms Linux, macOS and Windows.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Traditionally, C hasn't embraced reflection capabilities like some other programming languages. This is because C prioritizes efficiency and control. However, the lack of reflection doesn't necessarily mean a lack of introspection capabilities. Debuggers, for instance, rely heavily on debug information embedded within executable files. This information goes even beyond what reflection needs, encompassing details like types defined in the code, line numbers, source code references, symbol information and even location of variables and function arguments on the stack. One of the most common debug information formats is called &lt;a href="https://en.wikipedia.org/wiki/DWARF"&gt;DWARF&lt;/a&gt; and it’s a native for ELF format way to expose all needed for debuggers data. Even better, this format also works for Mach-O (MacOs executable format) and PE (Windows executable format).&lt;/p&gt;

&lt;p&gt;This begs the question: can't applications utilize this data directly to gain self-awareness? Here's why it's not as straightforward as it seems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DWARF has too much information - reflection requires just a subset. &lt;/li&gt;
&lt;li&gt;Shipping executables with full debug information can be undesirable due to increased size and potential security concerns.&lt;/li&gt;
&lt;li&gt;Utilities like &lt;code&gt;strip&lt;/code&gt; can remove debug information, rendering the application unusable.&lt;/li&gt;
&lt;li&gt;It may be worth separating reflection information which may be only for part of the application from debug information.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This implies a need for a specialized tool that can efficiently read, filter, and convert DWARF data (or its equivalent in other formats) into a format usable by the application. Enter &lt;a href="https://github.com/aodinokov/metac"&gt;Metac&lt;/a&gt;.&lt;br&gt;
Metac leverages this existing DWARF (or equivalent) information within the executable format to provide a targeted form of reflection for C code. This allows applications to access a relevant subset of the data, promoting introspection without the drawbacks of full debug information. Metac bridges the gap and allows C programs to query that data at runtime, enabling them to extract information about their own types, variables, and functions. This newfound self-awareness empowers C programs for more efficient debugging, dynamic behavior, and potential future functionalities.&lt;/p&gt;

&lt;p&gt;While DWARF data is available for object files on other platforms, macOS presents a slight hurdle. On macOS, DWARF information is typically not generated by default and requires the &lt;code&gt;dsymutil&lt;/code&gt; tool to create it explicitly for linked executable binary ONLY.&lt;/p&gt;

&lt;p&gt;To ensure consistent behavior across platforms, Metac takes a two-step approach that will work on macOS and compatible with other platforms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build with DWARF Generation&lt;/strong&gt;: The application is first built with special flags (&lt;em&gt;-g3 -D_METAC_OFF&lt;/em&gt;_) that enable DWARF generation but disable Metac functionalities during this stage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract and Integrate DWARF Data&lt;/strong&gt;: After the initial build, the DWARF information is extracted from the executable. Then, an additional C file containing reflection information is generated based on this data. Finally, the application is rebuilt with this additional file to include the necessary reflection capabilities and with Metac functionalities enabled.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This multi-step process might seem complex, but it's automated within a Makefile, simplifying the workflow for developers. It’s important to remember that Metac is getting DWARF from the complete built and linked application even though this process can be changed for other platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's delve into a practical example.&lt;/strong&gt; Imagine a C program that manages a complex data structure, like a linked list. Traditionally, debugging any issues within the structure requires manual code inspection. However, with Metac, the program can introspect its own linked list, examining elements like pointers and values. This allows for targeted debugging and manipulation of the list at runtime.&lt;/p&gt;

&lt;p&gt;Here's a simplified code example demonstrating how Metac could be used to examine a variable of type &lt;code&gt;struct test&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt;  // printf&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt; // free&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt;   // M_PI, M_E&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"metac/reflect.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;pi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;_uninitialized_field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;// we need to use this construction to wrap variable declaration&lt;/span&gt;
    &lt;span class="c1"&gt;// to get its type information&lt;/span&gt;
    &lt;span class="n"&gt;WITH_METAC_DECLLOC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decl_location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M_PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M_E&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;metac_value_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;METAC_VALUE_FROM_DECLLOC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decl_location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_entry_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metac_value_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// next will output "struct test t = "&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s = "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metac_value_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// next will output "{.y = -10, .c = 'a', .pi = 3.141593, .e = 2.718282, ._uninitialized_field = 0,};\n"&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;metac_value_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We include the &lt;code&gt;metac/reflect.h&lt;/code&gt; header for using Metac functions.&lt;/li&gt;
&lt;li&gt;We define a structure called test with various member variables.&lt;/li&gt;
&lt;li&gt;In main, we create a variable t of type struct test and initialize its members. Note: the construction &lt;code&gt;WITH_METAC_DECLLOC&lt;/code&gt; just makes sure that the arbitrary C-code from the second argument is located on the same line with the declaration location variable &lt;code&gt;decl_location&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;METAC_VALUE_FROM_DECLLOC(decl_location, t)&lt;/code&gt; to get a &lt;code&gt;metac_value_t&lt;/code&gt; representing the value of &lt;code&gt;t&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metac_entry_cdecl(metac_value_entry(p_val))&lt;/code&gt; retrieves a C-style string representing the declaration of &lt;code&gt;t&lt;/code&gt; (e.g., &lt;code&gt;struct test t&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metac_value_string(p_val)&lt;/code&gt; retrieves a string representing the actual value of &lt;code&gt;t&lt;/code&gt; with its member values (e.g., &lt;code&gt;{y=-10, c='a', pi=3.141593, e=2.718282, _uninitialized_field=0}&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;We free the allocated memory for both strings using free.&lt;/li&gt;
&lt;li&gt;Finally, we call &lt;code&gt;metac_value_delete(p_val)&lt;/code&gt; to clean up resources used by Metac.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This example demonstrates how Metac can be used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extract type information about a variable at runtime.&lt;/li&gt;
&lt;li&gt;Retrieve the actual value of the variable and its members.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is just a basic example, but it showcases the power of Metac for C code introspection.&lt;/p&gt;

&lt;p&gt;In order to build that it will be necessary to have Metac on the host where the build process is happening.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://docs.kernel.org/kbuild/kbuild.html"&gt;KBUILD&lt;/a&gt;-like Makefile to build the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="k"&gt;ifeq&lt;/span&gt; &lt;span class="nv"&gt;($(M),)&lt;/span&gt;
&lt;span class="nv"&gt;METAC_ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;../..

&lt;span class="nl"&gt;all&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;test target&lt;/span&gt;

&lt;span class="nl"&gt;target&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;METAC_ROOT&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;PWD&lt;span class="p"&gt;)&lt;/span&gt; target

&lt;span class="nl"&gt;clean&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;METAC_ROOT&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;PWD&lt;span class="p"&gt;)&lt;/span&gt; clean

&lt;span class="nl"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;$(&lt;/span&gt;MAKE&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;METAC_ROOT&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;PWD&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;all clean test&lt;/span&gt;
&lt;span class="k"&gt;endif&lt;/span&gt;

&lt;span class="nv"&gt;rules&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    target &lt;span class="se"&gt;\&lt;/span&gt;
    _meta_c_app &lt;span class="se"&gt;\&lt;/span&gt;
    c_app.reflect.c &lt;span class="se"&gt;\&lt;/span&gt;
    c_app &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="nv"&gt;LDFLAGS-c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-Lsrc&lt;/span&gt; &lt;span class="nt"&gt;-lmetac&lt;/span&gt;
&lt;span class="nv"&gt;LDFLAGS-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;-Lsrc&lt;/span&gt; &lt;span class="nt"&gt;-lmetac&lt;/span&gt;

&lt;span class="nv"&gt;in_c_app&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;main.o

&lt;span class="nv"&gt;TPL-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;bin_target
&lt;span class="nv"&gt;IN-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;in_c_app:.o&lt;span class="o"&gt;=&lt;/span&gt;.meta.o&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;POST-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;METAC_POST_META&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;TPL-c_app&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;bin_target
&lt;span class="nv"&gt;IN-c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;in_c_app&lt;span class="p"&gt;)&lt;/span&gt; c_app.reflect.o
&lt;span class="nv"&gt;DEPS-c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src/libmetac.a

&lt;span class="nv"&gt;TPL-c_app.reflect.c&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;metac_target
&lt;span class="nv"&gt;METACFLAGS-c_app.reflect.c&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;run metac-reflect-gen &lt;span class="p"&gt;$(&lt;/span&gt;METAC_OVERRIDE_IN_TYPE&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;IN-c_app.reflect.c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;_meta_c_app

&lt;span class="nv"&gt;TPL-target&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;phony_target
&lt;span class="nv"&gt;IN-target&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;c_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The part from &lt;code&gt;ifeq&lt;/code&gt; to &lt;code&gt;endif&lt;/code&gt; works exactly like in KBUILD. It’s possible to run &lt;code&gt;make all METAC_ROOT=&amp;lt;path to the Metac root&amp;gt;&lt;/code&gt; in order to build this example.&lt;/li&gt;
&lt;li&gt;The rest of the file is used to define rules which are going to be generated to build the example using multi-step process described in the beginning. The variable &lt;code&gt;rules&lt;/code&gt; list those:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rule &lt;code&gt;target&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;TPL-target&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;phony_target
&lt;span class="nv"&gt;IN-target&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;c_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which is generated as &lt;code&gt;.PHONY&lt;/code&gt; and that requires the final target &lt;code&gt;c_app&lt;/code&gt; to be built using the corresponding rules.&lt;/p&gt;

&lt;p&gt;Rule &lt;code&gt;c_app&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;TPL-c_app&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;bin_target
&lt;span class="nv"&gt;IN-c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;in_c_app&lt;span class="p"&gt;)&lt;/span&gt; c_app.reflect.o
&lt;span class="nv"&gt;DEPS-c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src/libmetac.a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a rule to build executable binary out of &lt;code&gt;main.o&lt;/code&gt; and &lt;code&gt;c_app.reflect.o&lt;/code&gt; and &lt;code&gt;libmetac.a&lt;/code&gt;. Make knows how to build main.o automatically from main.c. Where do we get &lt;code&gt;c_app.reflect.o&lt;/code&gt; from? From &lt;code&gt;c_app.reflect.c&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;Rule &lt;code&gt;c_app.reflect.c&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;TPL-c_app.reflect.c&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;metac_target
&lt;span class="nv"&gt;METACFLAGS-c_app.reflect.c&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;run metac-reflect-gen &lt;span class="p"&gt;$(&lt;/span&gt;METAC_OVERRIDE_IN_TYPE&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;IN-c_app.reflect.c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;_meta_c_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a rule which employs a &lt;code&gt;metac&lt;/code&gt; tool with arguments &lt;code&gt;run metac-reflect-gen $(METAC_OVERRIDE_IN_TYPE)&lt;/code&gt;. Input file is &lt;code&gt;_meta_c_app&lt;/code&gt;. This combination will instruct metac to read DWARF data from &lt;code&gt;_meta_c_app&lt;/code&gt;. Parameter &lt;code&gt;METAC_OVERRIDE_IN_TYPE&lt;/code&gt; is used to specify if metac must expect elf, macho or pe as input. &lt;code&gt;metac-reflect-gen&lt;/code&gt; is a go-template module name which generates &lt;code&gt;c_app.reflect.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Rule &lt;code&gt;_meta_c_app&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;TPL-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;bin_target
&lt;span class="nv"&gt;IN-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;in_c_app:.o&lt;span class="o"&gt;=&lt;/span&gt;.meta.o&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;POST-_meta_c_app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;METAC_POST_META&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to &lt;code&gt;c_app&lt;/code&gt;, but it uses &lt;code&gt;main.meta.o&lt;/code&gt; as source. The only difference between &lt;code&gt;main.meta.o&lt;/code&gt; and &lt;code&gt;main.o&lt;/code&gt; is that the first was built with flags &lt;code&gt;-g3 -D_METAC_OFF_&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we run make on macOS we should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% make
/Library/Developer/CommandLineTools/usr/bin/make &lt;span class="nt"&gt;-C&lt;/span&gt; ../.. &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/Users/user/Workspace/metac/examples/c_app_simplest &lt;span class="nb"&gt;test&lt;/span&gt;
/Library/Developer/CommandLineTools/usr/bin/make &lt;span class="nt"&gt;-C&lt;/span&gt; ../.. &lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/Users/user/Workspace/metac/examples/c_app_simplest target

cc &lt;span class="nt"&gt;-I&lt;/span&gt;./include &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-MMD&lt;/span&gt; &lt;span class="nt"&gt;-MF&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/main.d &lt;span class="nt"&gt;-MP&lt;/span&gt; &lt;span class="nt"&gt;-MT&lt;/span&gt; &lt;span class="s1"&gt;'/Users/user/Workspace/metac/examples/c_app_simplest/main.o /Users/user/Workspace/metac/examples/c_app_simplest/main.d'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/main.o /Users/user/Workspace/metac/examples/c_app_simplest/main.c

cc &lt;span class="nt"&gt;-I&lt;/span&gt;./include &lt;span class="nt"&gt;-g3&lt;/span&gt;  &lt;span class="nt"&gt;-D_METAC_OFF_&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-MMD&lt;/span&gt; &lt;span class="nt"&gt;-MF&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/main.meta.d &lt;span class="nt"&gt;-MP&lt;/span&gt; &lt;span class="nt"&gt;-MT&lt;/span&gt; &lt;span class="s1"&gt;'/Users/user/Workspace/metac/examples/c_app_simplest/main.meta.o /Users/user/Workspace/metac/examples/c_app_simplest/main.meta.d'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/main.meta.o /Users/user/Workspace/metac/examples/c_app_simplest/main.c

cc /Users/user/Workspace/metac/examples/c_app_simplest/main.meta.o &lt;span class="nt"&gt;-Lsrc&lt;/span&gt; &lt;span class="nt"&gt;-lmetac&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/_meta_c_app

&lt;span class="o"&gt;(&lt;/span&gt;which dsymutil&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; dsymutil /Users/user/Workspace/metac/examples/c_app_simplest/_meta_c_app &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Couldn't find dsymutil"&lt;/span&gt;
/usr/bin/dsymutil

./metac run metac-reflect-gen &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'path_type: "macho"'&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'path: "/Users/user/Workspace/metac/examples/c_app_simplest/_meta_c_app"'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.c

cc &lt;span class="nt"&gt;-I&lt;/span&gt;./include &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-MMD&lt;/span&gt; &lt;span class="nt"&gt;-MF&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.d &lt;span class="nt"&gt;-MP&lt;/span&gt; &lt;span class="nt"&gt;-MT&lt;/span&gt; &lt;span class="s1"&gt;'/Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.o /Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.d'&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.o /Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.c

cc /Users/user/Workspace/metac/examples/c_app_simplest/main.o /Users/user/Workspace/metac/examples/c_app_simplest/c_app.reflect.o &lt;span class="nt"&gt;-Lsrc&lt;/span&gt; &lt;span class="nt"&gt;-lmetac&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /Users/user/Workspace/metac/examples/c_app_simplest/c_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we run the application we’ll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;% ./c_app
struct &lt;span class="nb"&gt;test &lt;/span&gt;t &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;.y &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;, .c &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;, .pi &lt;span class="o"&gt;=&lt;/span&gt; 3.141593, .e &lt;span class="o"&gt;=&lt;/span&gt; 2.718282, ._uninitialized_field &lt;span class="o"&gt;=&lt;/span&gt; 0,&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example can be found &lt;a href="https://github.com/aodinokov/metac/tree/main/examples/c_app_simplest"&gt;here&lt;/a&gt;.&lt;br&gt;
More information on how to use metac can be found &lt;a href="https://github.com/aodinokov/metac/blob/main/doc/demo/README.md#how-to-demo"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;:&lt;br&gt;
Metac isn't just a tool; it's a path to self-improvement for your C code. With DWARF's insights and metac's interpretation, your programs can shed light on their "unconscious" behaviors and unlock their full potential.&lt;/p&gt;

</description>
      <category>c</category>
      <category>reflection</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
