Reputation: 364
I am using X macros to generate functions setting GPIOs to 0
or 1
(I generate around 60 functions to set around 30 GPIOs). Here is an example (I have just written this example, so the syntax may be wrong):
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs \
X(Pin0, 0) \
X(Pin1, 1) \
X(Pin2, 2) \
X(Pin3, 3)
I generate the functions to access to these GPIOs:
#define X(pin_name, pin_nb) \
static void SetOn_GPIO##pin_name (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
The same process exists for SetOff_GPIOXXX
functions.
Is there a way I can access the function generated above by the compiler as SetOn_GPIOPin2
in an other part of the program without directly writing the function name? (In order to keep the code as global as possible)
At the end of preprocessing, we should only have SetOn_GPIOPin2();
(and not every X-macro entries) generated from X-Macro.
Before pre-processing:
void foo ()
{
/* some code */
/*
* Macro to generate the desired function.
* For e.g: SetOn_GPIOPin2();
*/
/* some code */
}
After pre-processing:
void foo ()
{
/* some code */
/* Function resulting of the pre-processing */
SetOn_GPIOPin2();
/* some code */
}
Upvotes: 3
Views: 508
Reputation: 4169
You can add another field to your X macro table, and then use this neat trick (based on macro token concatenation) to gate what gets generated.
For example, add a field to your table:
/* X(pin_name, pin_nb, call_in_foo) */
#define CPLD_GPIOs \
X(Pin0, 0, false) \
X(Pin1, 1, false) \
X(Pin2, 2, true) \
X(Pin3, 3, false)
Then define the true and false variants (false does nothing in this case):
#define GPIO_ON_true(pin_name) SetOn_GPIO##pin_name();
#define GPIO_ON_false(pin_name)
And then use macro token concatenation in your X definition:
void foo ()
{
/* some code */
#define X(pin_name, pin_nb, call_in_foo) GPIO_ON_##call_in_foo(pin_name)
CPLD_GPIOs
#undef X
/* some code */
}
Upvotes: 0
Reputation: 181159
From comments on the question, your objective appears to be to protect against the case in which your X macro is modified to produce differently-named functions. If that's so, then I think you're making unnecessary work for yourself: whether those names are changed is under your (and any other project developers') control, and a name change such as you are concerned about will not go unnoticed very long. So don't change them.
But if you're determined to go this route then no, there is no way to make the preprocessor extract the function names generated by your macros from their larger replacement text. Instead, you would need to inject them, via the same macro, into both the X macros and your other code. Like this, perhaps:
/* X(pin_name, pin_nb) */
#define CPLD_GPIOs(gen) \
X(Pin0, 0, gen) \
X(Pin1, 1, gen) \
X(Pin2, 2, gen) \
X(Pin3, 3, gen)
// Generates the wanted function names:
#define GPIO_ON(pin_name, pin_nb) SetOn_GPIO##pin_name
#define X(pin_name, pin_nb, gen) \
static void gen(pin_name, pin_nb) (void) { \
SetOn_GPIOpins(pin_nb);\
}
CPLD_GPIOs
#undef X
// ...
void some_function(void) {
GPIO_ON(pin_name, pin_nb)();
}
But note well that although this technique might have other applications, such as to generating multiple sets of functions with the same set of X
macros, it just kicks the can down the road with respect to the specific objective you described. You can rely on the name-generator macro to produce the same names for function declarations and function calls, but you still have the problem that the X
macro can be modified to generate function declarations with different names.
Upvotes: 1
Reputation: 63154
Using our trusty Boost.Preprocessor rocket launcher, this is preatty easy:
#include <boost/preprocessor/tuple/rem.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#define X_SELECT_PIN(pin_nb, selected_pin_nb, ...) \
BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_IF( \
BOOST_PP_EQUAL(pin_nb, selected_pin_nb), \
(__VA_ARGS__), \
() \
))
// Usage
#define X(pin_name, pin_nb)\
X_SELECT_PIN(pin_nb, 2, SetOn_GPIO##pin_name (void);)
CPLD_GPIOs
#undef X
This uses BOOST_PP_IF
to expand your pattern only for the selected pin. The added parentheses and BOOST_PP_TUPLE_REM_CTOR
are there to protect the macro from expansions containing commas.
Upvotes: 0