2

I've defined an object-like macro and a function-like macro (from this question).

#define SYSTEM windows
#define CALL(function, ...)   (function)(__VA_ARGS__)

Given this definition, CALL(foo, arg1, arg2) turns into foo(arg1, arg2).

I want CALL(foo, args) to turn into x__foo(args), x being whatever SYSTEM is defined to.

I have tried:

#define CALL(function, ...)   SYSTEM##__function(__VA_ARGS__)
#define CALL(function, ...)   (SYSTEM)##__##(function)(__VA_ARGS__)
#define CALL(function, ...)   ((SYSTEM)##__##(function)(__VA_ARGS__)

They all result in compiler errors.

How can I define CALL so that it concatenates the value of SYSTEM, __, and the value of function?

Community
  • 1
  • 1
MD XF
  • 7,860
  • 7
  • 40
  • 71

2 Answers2

6

You're going to need a few more levels of indirection to concatenate (paste) those values. The C preprocessor attempts to paste exactly what it sees. If what it's seeing is a macro or a value passed to a function, it doesn't realize that.

  • MACRO##SOMETHINGELSE will produce MACROSOMETHINGELSE.
  • (MACRO)##SOMETHINGELSE will result in an error upon compilation, because the preprocessor is attempting to paste the parenthesis.
  • SOMETHINGELSE##VALUEPASSEDTOMACRO will result in SOMETHINGVALUEPASSEDTOMACRO.

None of these are what you want, obviously. To add the indirection necessary to concatenate object-like-macro values and values passed to a function-like-macro, use two more definitions.

#define _cat(x, y) x ## y
#define cat(x, y) _cat(x, y)

Then you can define CALL to fit your needs.

#define SYSTEM windows
#define CALL(function, ...)   cat(cat(SYSTEM, __), function) (__VA_ARGS__)

Writing CALL(foobar, x, y) calls windows__foobar(x, y) as desired.

MD XF
  • 7,860
  • 7
  • 40
  • 71
4
#define SYSTEM windows
#define PASTE_CALL(prefix, function, ...) prefix ## __ ## function(__VA_ARGS__)
#define EVAL_CALL(prefix, function, ...) PASTE_CALL(prefix, function, __VA_ARGS__)
#define CALL(function, ...) EVAL_CALL(SYSTEM, function, __VA_ARGS__)

CALL(foo, arg1, arg2)

As desired, this generates:

# 1 "paste.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "paste.c"





windows__foo(arg1, arg2)
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278