Как правильно вызвать макрос в макросе
Мне необходимо бъеденить несколько передаваемых в макрос параметров, в один целый, для этого есть 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 шт):
Первый подход обработки макроса с аргументами ( 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
Все потому, что __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__ начнет раскрывать макросы в параметрах, и все заработает.