Products > Programming

Macro functions in headers

(1/5) > >>

dunkemhigh:
Title doesn't really cover it properly, so here is what it is:

I have a C module which has a lot of functions which all basically do the same thing apart from using different variables. They are get/set functions for the config, reading and writing NVS. So the string functions might look like this (it is ESP-IDF):


--- Code: ---void confSetURL(char *url)
{
    nvs_set_string(hconfig, NVS_KEY, url);
    nvs_commit(hconfig);
}
--- End code ---

OK, so I am writing a macro that saves me typing that all out:


--- Code: ---#define confSetStr(NAME, KEY) \
void confSet##NAME(char *str) \
{ \
nvs_set_str(hconfig, KEY, str); \
nvs_commit(hconfig); \
}
--- End code ---

and I can then do lots of line like:


--- Code: ---confSetStr(URL, CFG_KEY_URL);
--- End code ---

and call it:


--- Quote ---confSetURL("www.google.com");
--- End quote ---

Except, I have to manually add the real function prototype to the .h in order to achieve that, and I am now looking at not just typos but a non-correlation between header prototype and macro instantiation.

Any way around this?

(I have no doubt someone will say that this - the many nearly identical functions - is not the way to do this, but it's the getting callable prototypes into the header that I'm really interested in here.)

langwadt:
maybe something like the last answer here?

https://stackoverflow.com/questions/49099976/how-do-you-define-functions-in-header-files

SiliconWizard:
Several ways to deal with it. Two of them:

- Either define an additional macro to generate the prototypes. Would just be:

--- Code: ---#define confSetStr_Proto(NAME)    void confSet##NAME(char *str)
--- End code ---
And then in the header file, you'd have to declare the prototypes like so:

--- Code: ---confSetStr_Proto(URL);
--- End code ---

- Or you could define the functions themselves inside the header file. You just need to qualify them static. The added benefit is that they'll get inlined everywhere they'll be called when optimizations are enabled. The drawback is that: possibly excess code size if the functions in question are large, but in the case of very small functions like getters and setters, that's IMHO a good approach:

--- Code: ---#define confSetStr(NAME, KEY) \
static void confSet##NAME(char *str) \
{ \
nvs_set_str(hconfig, KEY, str); \
nvs_commit(hconfig); \
}
--- End code ---
And then in the header file, you'd have to define the functions like so:

--- Code: ---confSetStr(URL, CFG_KEY_URL)
--- End code ---
(Note that you can't add a final semicolon as you did in your example for defining functions with a body. The semicolon right after the final brace of the function's body will normally give a syntax error.)

brucehoult:
Put all the calls to confSetStr() in a .inc file (name doesn't matter, it's just a convention) and then #include it into both the header and the C file, with different definitions of the macro in each (and #undef it after)

As I do here:

https://github.com/brucehoult/trv

dunkemhigh:

--- Quote from: langwadt on December 02, 2021, 12:54:06 am ---maybe something like the last answer here?

https://stackoverflow.com/questions/49099976/how-do-you-define-functions-in-header-files

--- End quote ---

I couldn't see how that was relevant, sorry.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version