Consider the macro
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d))
I would like to define the arguments a,b,c,d in another macro. So I have done this:
#define DEBUG_HOST_IP4 192, 168, 0, 123
IP4_ADDR(&debug_host, 192, 168, 0, 123 );
IP4_ADDR(&debug_host, DEBUG_HOST_IP4 );
The first call to IP4_ADDR compiles succesfully, while the second one fails with
error: macro "IP4_ADDR" requires 5 arguments, but only 2 given
IP4_ADDR(&debug_host, DEBUG_HOST_IP4 );
Is there a way to make DEBUG_HOST_IP4
expand properly, so the IP4_ADDR
macro can work as intended?
EDIT: The IP4_ADDR macro comes from a third-party library, which I would rather not touch, and risk breaking somebody else's code. Of course, implementing my own version is an option.
Short answer yes. You can nest defines and macros like that - as many levels as you want as long as it isn't recursive.
A parameter can be either a simple string or a quoted string. It can be passed by using the standard method of putting variables into shared and profile pools (use VPUT in dialogs and VGET in initial macros). This method is best suited to parameters passed from one dialog to another, as in an edit macro.
The process to redefine a Macro is: Macro must be defined. When, you want to redefine the Macro, first of all, undefined the Macro by using #undef preprocessor directive. And, then define the Macro again by using #define preprocessor directive.
To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. The parameters must be valid C identifiers, separated by commas and optionally whitespace.
In this case, you can make your outer macro a varargs macro:
#define IP4_ADDR(ipaddr, ...) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(__VA_ARGS__))
The macro invocation must have the correct number of arguments. The inner macro invocation works because arguments are expanded before the body is rescanned.
The varargs syntax allows you to either supply the four arguments or use a macro which expands to them.
If you don't want to alter the definition of IP_ADDR
, you invoke it indirectly through a wrapper macro:
#define CALL(macro, __VA_ARGS__) macro(...)
// ...
CALL(IP4_ADDR, &debug_host, DEBUG_HOST_IP4 );
If you can't alter IP4_ADDR, this is still pretty easy; just wrap it:
#define MY_IP4_ADDR(...) IP4_ADDR(__VA_ARGS__)
During the translation (which just moves all of the arguments over, whatever they are), any macros will expand. Then just use your wrapped version in the code.
MY_IP4_ADDR(&debug_host, 192, 168, 0, 123 );
MY_IP4_ADDR(&debug_host, DEBUG_HOST_IP4 );
And you should be good to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With