Как правильно вызвать макрос в макросе

Мне необходимо бъеденить несколько передаваемых в макрос параметров, в один целый, для этого есть 2 макроса, string_join и helper_name (префиксы опустил).

Но когда макрос должен развернуться к примеру с таким вызовом: KODIK_DEFINE_STRUCT(api);

Ожидаемый мной разворот:

typedef struct __kodik_api_s kodik_api_t;

Но на деле, я получаю вот такой вывод:

 ../src/../include/kodik/kodik.h:50:94: error: expected ')' before ',' token
    50 | #   define __kodik_helper_name__(X, Y) __kodik_string_join__( kodik_, __kodik_string_join__(X, Y) )
       |                                                                                              ^
 ../src/../include/kodik/kodik.h:46:45: note: in definition of macro '__kodik_string_join__'
    46 | #   define __kodik_string_join__(X, Y) X ## Y
       |                                             ^
 ../src/../include/kodik/kodik.h:54:53: note: in expansion of macro '__kodik_helper_name__'
    54 | #   define KODIK_DEFINE_STRUCT(NAME) typedef struct __kodik_helper_name__(NAME, _s) __kodik_helper_name__(NAME, _t)
       |                                                     ^~~~~~~~~~~~~~~~~~~~~
 ../src/main.c:3:1: note: in expansion of macro 'KODIK_DEFINE_STRUCT'
     3 | KODIK_DEFINE_STRUCT(api);
       | ^~~~~~~~~~~~~~~~~~~

Как это можно исправить что бы вызываемый в макросе макрос был развернут?

#ifndef __kodik_string_join__
#   define __kodik_string_join__(X, Y) X ## Y
#endif // !__kodik_string_join__

#ifndef __kodik_helper_name__
#   define __kodik_helper_name__(X, Y) __kodik_string_join__(kodik_, __kodik_string_join__(X, Y))
#endif // !__kodik_helper_name__

#ifndef KODIK_DEFINE_STRUCT
#   define KODIK_DEFINE_STRUCT(NAME) typedef struct __kodik_helper_name__(NAME, _s) __kodik_helper_name__(NAME, _t)
#endif // !KODIK_DEFINE_STRUCT

#ifndef KODIK_DECLARE_STRUCT
#   define KODIK_DECLARE_STRUCT(NAME) struct __kodik_helper_name__(NAME, _s)
#endif // !KODIK_DECLARE_STRUCT

Ответы (2 шт):

Автор решения: AlexGlebe

Первый подход обработки макроса с аргументами ( XValue, YValue ) :

__kodik_string_join__(kodik_, __kodik_string_join__(X, Y))

приведёт к добавлению приставки к самому имени макроса и замене всех аргументов :

kodik___kodik_string_join__(XValue, YValue)

Второй подход уже не заметит __kodik_string_join__. Вам проще не использовать лишние макросы, а сделать всё напрямую.

#   define __kodik_helper_name__(X, Y) kodik_ ## X ## Y
→ Ссылка
Автор решения: HolyBlackCat

Все потому, что __kodik_string_join__ плохо написан. Он не раскрывает макросы в своих параметрах, и ничем не лучше ##.

Если обернуть ## во вложенный макрос:

#define __kodik_string_join__(X, Y) __kodik_string_join__0(X, Y)
#define __kodik_string_join__0(X, Y) X ## Y

То __kodik_string_join__ начнет раскрывать макросы в параметрах, и все заработает.

→ Ссылка