Home > OS >  define a function in a c macro with a dynamic name coming from a function-like C macro
define a function in a c macro with a dynamic name coming from a function-like C macro

Time:01-18

okay this sounds weird, the title is kinda confusing but heres what i mean basically :

#define make_name(id) cool_name_##id
#define my_cool_macro(id, type) void fun_##make_name(id)(type arg1)

my_cool_macro(hello, char);

this should expand to

/*
 * passed through my_cool_macro
 *                 vvvvv
 */
void fun_cool_name_hello(char arg1);
/*   ~~~~^^^^^^^^^^^^^^^ */
  • ~ -- my_cool_macro
  • ^ -- make_name

i dont have a better way to explain this, any way to make this work ?

basically :

  • define a function-like macro which can generate names
  • define another function-like macro which calls to the defined name creating macro with an argument passed to the function creator macro

why am i doing this

im kinda trying to implement templaces in c using macros and as you know templated functions can have different types and i want to mangle the names but not repeat the cool_name_... because what if i want to change the cool_name to some_name

the solution should also work similarly to my example, so fun_##make_name(hello) should work as should hello_##make_name(hello) and ewuihewuifh_##make_name(hello) without me needing to define a macro for every change

CodePudding user response:

You can do:

#include <stdio.h>

#define join(x, y)  x##y
#define make_name_l(fn, id, arg_type) fn##id(arg_type)
#define make_name(fn, id, arg_type) make_name_l(fn, id, arg_type)
#define my_cool_macro(ret_type, id, arg_type) ret_type make_name(join (fun_, cool_name_), id, arg_type)

my_cool_macro(void, hello, char);

int main (void) {
    fun_cool_name_hello('a');
    return 0;
}
void fun_cool_name_hello (char a) {
    printf ("In function : %s, arg : %c\n", __func__, a);
}

Additional:

In case, if you want to make it work with any type or number of arguments then you can use ellipsis (...) and __VA_ARGS__.

include <stdio.h>

#define join(x, y)  x##y
#define make_name_l(fn, id, ...) fn##id(__VA_ARGS__)
#define make_name(fn, id, ...) make_name_l(fn, id, __VA_ARGS__)
#define my_cool_macro(ret_type, id, ...) ret_type make_name(join (fun_, cool_name_), id, __VA_ARGS__)

my_cool_macro(void, hello, char);
my_cool_macro(int, multiple_args, char, int, const char *);
my_cool_macro(void, no_args, void);

int main (void) {
        const char * str = "test";
        fun_cool_name_hello('a');
        fun_cool_name_multiple_args('x', 5, str);
        fun_cool_name_no_args();
        return 0;
}
void fun_cool_name_hello (char a) {
        printf ("In function : %s, arg : %c\n", __func__, a);
}

int fun_cool_name_multiple_args (char c, int i, const char * pstr) {
        printf ("In function : %s, c : %c, i : %d, str : %s\n", __func__, c, i, pstr);
        return i;
}

void fun_cool_name_no_args (void) {
        printf ("In function : %s\n", __func__);
}

Output:

# ./a.out
In function : fun_cool_name_hello, arg : a
In function : fun_cool_name_multiple_args, c : x, i : 5, str : test
In function : fun_cool_name_no_args

https://godbolt.org/z/d67MWjasz

CodePudding user response:

You could have a macro that creates the prototype along with its type, as well as one that makes your custom name.

#define name(f) cool_name_##f
#define make_function(type, name, arg) type fun_name(arg)
#include <stdio.h>

#define name(f) cool_name_##f
#define make_function(type, name, arg) type fun_name(arg)

make_function(void, name(hello), int);

void cool_name_fun_hello(int f) {
    printf("%d\n", f);
}

int main(void) {
    cool_name_fun_hello(1);
}
  • Related