I'm making look-up tables between 2 drivers. I use an enum starting at index 0, which is passed to a look-up table to return an integer. This works fine.
// In library
#define LIB_FEATURE_1 0x10
#define LIB_FEATURE_2 0x22
#define LIB_FEATURE_3 0x44
#define LIB_FEATURE_4 0x42
// In my costum driver
enum features_s {
my_feature_a = 0,
my_feature_b = 1,
my_feature_c = 2
};
const int feature_tbl[] = {
LIB_FEATURE_2, // Maps my_feature_a to LIB_FEATURE_2
0xFF, // Maps my_feature_b to an error code because this
// feature is not present in library
LIB_FEATURE_4 // Maps my_feature_c to LIB_FEATURE_4
};
// In app
int value = feature_tbl[my_feature_a];
The library contains some more complicated macros (setting registers in an embedded system) :
// In library
#define LIB_FEATURE_1 do {
//does black magic
} while(0)
#define LIB_FEATURE_2 do {
//does white magic
} while(0)
#define LIB_FEATURE_3 do {
//does yellow magic
} while(0)
#define LIB_FEATURE_4 do {
//does purple magic
} while(0)
// In my costum driver
enum features_s {
my_feature_a = 0,
my_feature_b = 1,
my_feature_c = 2
};
/*
* something missing here. I want this mapping :
* my_feature_a executes LIB_FEATURE_2();
* my_feature_b executes nothing
* my_feature_c executes LIB_FEATURE_4();
*/
// In app
SOME_KIND_OF_LOOK_UP_TABLE[my_feature_a]();
Is it possible to create a const table, or a macro that takes an index as argument and executes the right feature?
I also tried macro concatenation, but it doesn't seem to work.
I tried using a const table, and a macro concatenations
CodePudding user response:
Runtime version:
//function prototype
typedef void (*my_lib_feature_function)();
//implement feature functions
//we need an address, therefore real functions instead of macros
static void my_lib_feature_function_1() { /* feature magic 1 */ }
static void my_lib_feature_function_2() { /* feature magic 2 */ }
static void my_lib_feature_function_3() { /* feature magic 3 */ }
static void my_lib_feature_function_4() { /* feature magic 4 */ }
//feature table (lookup table)
//organize as you see fit, extend or shorten it, but
//take care of the right indices (enum values)
static const my_lib_feature_function function_table[] = {
my_lib_feature_function_2, //index 0 -> my_feature_a
NULL, //index 1 -> my_feature_b
my_lib_feature_function_4 //index 2 -> my_feature_c
};
//invoker
//param feature is the index to the lookup table
static void invoke_my_lib_feature(enum features_s feature)
{
if (function_table[feature] != NULL) //if entry exists
function_table[feature](); //execute it
}
//In app
/*either*/ //invoke_my_lib_feature(my_feature_a);
/*and/or*/ //invoke_my_lib_feature(my_feature_b);
/*and/or*/ //invoke_my_lib_feature(my_feature_c);
Compiletime version:
//pp util (concatenation)
#define CAT(A,B) CAT_(A,B)
#define CAT_(A,B) A##B
//instead of enum (unfortunately, we can't use enum values here)
#define MY_FEATURE_A 0
#define MY_FEATURE_B 1
#define MY_FEATURE_C 2
//feature table
#define LIB_FEATURE_ENTRY_0 LIB_FEATURE_2 //-> MY_FEATURE_A
#define LIB_FEATURE_ENTRY_1 //empty //-> MY_FEATURE_B
#define LIB_FEATURE_ENTRY_2 LIB_FEATURE_4 //-> MY_FEATURE_C
//invoker
#define INVOKE_LIB_FEATURE(IDX) CAT(LIB_FEATURE_ENTRY_,IDX)
//In App
/*either*/ //INVOKE_LIB_FEATURE(MY_FEATURE_A); //expands to text after LIB_FEATURE_2
/*and/or*/ //INVOKE_LIB_FEATURE(MY_FEATURE_B); //empty
/*and/or*/ //INVOKE_LIB_FEATURE(MY_FEATURE_C); //expands to text after LIB_FEATURE_4