I am unsure about where to write the declaration and the call of a macro that replaces the code with a function. I do not really know if I should write the macro to the .h or .c file.
Before reading some stuff on the best ways to create libraries, I was just putting all the code in a header file and including it on my main, i.e.
#ifndef LIB
#define LIB
#define def_func(type) \
type func(type x) \
{ \
// Do something
}
func(int)
#endif
Some other functions use these defined functions so I had to call the macro to the .h file.
Firstly, I think that a few small edits are needed in the code from the question:
#ifndef LIB
#define LIB
#define def_func(type) \
type func(type x) \
{ \
/* Do something */ \
}
def_func(int)
#endif
The question does not detail what objective is being achieved, but I would assume that the goal is to create something that behaves like a template in C++, where the code is defined in one place and instances are created for different types by using the macro def_func.
One thing to be aware of is if you are using def_func more than once in your project, then you are going to have linker errors due to the same global symbol being used in multiple places, even if def_func is used in separate files. This could be avoided by making the function static if def_func is used multiple times but never more than once in the same file. Although, this would restrict the function from being called from multiple files.
Global symbol redefinition could also be avoided by adding another argument to the #define as follows:
#define def_func(func, type) \
type func(type x) \
{ \
/* Do something */ \
}
This would allow the function identifier to be specified uniquely. For example:
def_func(func_int, int)
would expand to:
int func_int(int x)
{
/* Do something */
}
This way a unique identifier would be created for each instance.
The #define should be placed in the header file if you intend to use the macro from multiple C source files. The macro should be used within C source files only, since using this in the header file would instantiate an object with the same global symbol in each case the header file is included. Although, this would be allowable if the functions are defined as static.
Lastly, if you plan to call the function created from multiple locations, you will need a macro that can be used in a header file associated with the module defining the function to prototype the function. For example:
#define def_func_proto(func, type) \
type func(type x)
So to sum it up, your library .h file would contain:
#define def_func(func, type) \
type func(type x) \
{ \
/* Do something */ \
}
#define def_func_proto(func, type) \
type func(type x)
Then using the integer case as an example, the C source file may include:
def_func(func_int, int)
Which would expand to (note that the actual expansion will not have line breaks):
int func_int(int x)
{
/* Do something */
}
In this case, the header file may contain:
def_func_proto(func_int, int);
Which would expand to:
int func_int(int x);
Finally, I would note that am not certain that this is a good programming practice, in general. You will want to be very cautious in implementing this in your program.
Related
I have a macro that should be used both in my source file and header one. However I don't wan't other code linked to the final object to access that macro (more than anything else I don't want the macro to go causing unexpected errors in other files). I thought about using a macro with a long and complicated name that will be unlikely used from other code, however this solution kinda looks ugly to me. Obviously the most simple solution would be to undefine the macro in some way, however if I define the macro in the header and then undefine it – I think – I won't be able to access it anymore from the source file. What should I do?
// hi.h
#define string char *
void greet(string x);
// hi.c
#include "hi.h"
void greet(string x) {
printf("Hi!");
}
Okay, don't kill me, this was just an example, i know #define string char * is horrible.
Last minute thought: Maybe I can underfine the macro at the end of the source file, is this acceptable to do?
I guess you could conditionally "undefine" macro at the end of the header when the a magic macro is not defined. The blessed source file would have to define this macro prior to including a header.
// header.h
...
#ifndef MAGIC_MACRO
#undef string
#endif
// common source
#include "header.h"
// blessed source
#define MAGIC_MACRO
#include "header.h"
This solution will work great as long as no macro defined inside the header uses string macro.
What should I do?
Pick option 1 a macro with a long and complicated name that will be unlikely used from other code as it's the simplest and most obvious. Do not use a complicated name - just use a name so that you and other developers will know it's a private symbol, that's all.
// hi.h
// this macro is private
#define _lib_string char *
Remember about reserved words. Example: https://github.com/GNOME/glib/blob/main/glib/glib-private.h#L32 .
he most simple solution would be to undefine the macro in some way, however if I define the macro in the header and then undefine it – I think – I won't be able to access it anymore from the source file
If you go this way, you'll end up with spaghetti code, where some global state affects what you have. For example:
// hi.h
#define string char *
void greet(string x);
#ifndef FROM_HI_C
#undef string
#endif
// hi.c
#define FROM_HI_C
#include "hi.h"
void greet(string x) {
printf("Hi!");
}
Maybe I can underfine the macro at the end of the source file, is this acceptable to do?
Other files see only the header file - they are unaffected by anything in the source file.
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 */
}
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.
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.
I am trying to simulate generics in C by having some preprocessor definitions for a matrix type. Here is an excerpt of that:
#define __matrix_struct(TYPE) \
struct { \
uint32_t sz; \
TYPE **ptr; \
}
#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *
#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)
#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
__matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
uint32_t i; \
__matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
for (i = 0; i < sz; ++i) { \
m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
} \
return m; \
}
#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
uint32_t i; \
for (i = 0; i < m->sz; i++) { \
free(m->ptr[i]); \
} \
free(m->ptr); \
free(m); \
}
#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)
In another file, byte_matrix.h, I am trying to define a matrix of uint8_t values, as follows:
#include "matrix.h"
typedef uint8_t byte;
__matrix_typedef(byte);
__matrix_allocator(byte)
__matrix_deallocator(byte)
When I try to compile, I get the following errors:
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here
I cannot understand why it would point to times to the same line and complain about that definition, since every header I wrote has include guards. Could you please explain this to me? Also if you know of a better approach to my problem, please let me know. Thanks.
Also I need to compile with -std=c99 if that matters in this case.
A quick fix would be to add static to your function definitions. This will create a static copy of these functions in each compilation unit which references the header. If you want the functions to be inlined every time, this is the way to go.
An alternative way to do it would be to keep function declarations in a .h file, and actual definitions in a single .c file. This approach will avoid duplication, and the compiler will not inline them (unless your linker supports link time optimization).
The reason is that you are including this header file in multiple compilation units. After the preprocessor does all the textual replacements, you end up with actual separate function definitions inside your .c files. And if you don't specify that you want them to be static, they are by default extern, which means that now the compiler doesn't know how to differentiate them if some other part of the code wants to call them.
This is what you basically do whenever you create a header file: you create a list of declarations which will be included in many compilation units, but there is always a single extern definition in a single .c file.
Another way (relative to the proposed by Groo) is to create two macros.
__matrix_allocator_declare with just prototype of function -- for h-file(s)
__matrix_allocator_define with function body -- for one (selected by you) c-file
This way requires to handle two macros and to not forget add function-body macro in some file, but (and it is more important for embedded applications on small microcontrollers) it guarantees that only one function instance will consume memory.
Please,
could you tell me what does the code below do?
...code...
#include file.h
...code...
I was used to put includes a the beggining of each file. I have never seen this before and also wasn't able to find anything in the internet.
#include is a pre-processor directive that takes the file given as the argument and dumps its contents in the current file. Typically, this is used to include definitions of commons functions from header files, but there's no necessity to use it in that way.
It's usage is not limited to the starting of the file, but note that the variables, macros or functions declared in this header will not be usable before the include statement even if on the same file.
As everyone tells you #include can be used every where (provided it is on its own logicial line). And there are cases where you want to #include several times the same file. Read first the X macro wikipage, and the C preprocessor wikipage.
And I have a concrete example in my MELT monitor (related to MELT ...).
I have a predef-monimelt.h (generated) file containing lines like
MOM_PREDEFINED_NAMED( name, id,hash) e.g.
MOM_PREDEFINED_NAMED(GET,_9dsak0qcy0v_1c5z9th7x3i,1573018885)
MOM_PREDEFINED_NAMED(HEAD,_47fatww79x6_vh8ap22c0ch,3922245622)
MOM_PREDEFINED_NAMED(web_handler,_7sav6zery1v_24sa6jwwu6c,2339220870)
#undef MOM_PREDEFINED_NAMED
My monimelt.h file (a real header file) define external pointers and an enum, so has notably:
// declare the predefined
#define MOM_PREDEFINED_NAMED(Name,Id,H) extern momitem_t* mom_named__##Name;
#include "predef-monimelt.h"
/// declare the hash of the predefined as an enum
#define MOM_PREDEFINED_NAMED(Name,Id,H) mom_hashname__##Name = H,
enum {
#include "predef-monimelt.h"
};
My main.c file contains notably a routine :
// if this routine is compiled, we are sure that all predefined hashes
// are unique
const momitem_t *
mom_predefined_item_of_hashcode (momhash_t h) {
switch (h) {
#define MOM_PREDEFINED_NAMED(Nam,Id,Hash) case Hash: return mom_named__##Nam;
#include "predef-monimelt.h"
default:
return NULL;
}
}
but my items.c includes the predef-monimelt.h file twice (to create the predefined items at initialization, and to define their variables):
void mom_create_predefined_items (void) {
int nbnamed = 0;
#define MOM_PREDEFINED_NAMED(Nam,Id,H) do { \
mom_named__##Nam = mom_make_item_of_identcstr(#Id); \
mom_named__##Nam->i_space = momspa_predefined; \
mom_register_item_named_cstr (mom_named__##Nam, #Nam); \
nbnamed ++; \
} while(0);
#include "predef-monimelt.h"
} // end of mom_create_predefined_items
// declare the predefined
#define MOM_PREDEFINED_NAMED(Nam,Id,H) momitem_t* mom_named__##Nam;
#include "predef-monimelt.h"
FWIW, the MELT monitor is GPLv3+ licensed software
I have one piece of code that I can use for the same function on different sets of data which are defined in different header files . These header files may have the same variable defined differently.
I can pass a parameter to the code when I call it to specify which dataset I want to perform the function on.
What I would like to do is pass this parameter to the code where if the parameter equals X then I use headerX, or if parameter equals Y I use headerY.
It is my understanding that header files must be included before MAIN. Is it possible to include the header file after MAIN so that I can write an if/else statement to determine which header file I am calling?
If I can't do that then please help me figure this out.
You could use #ifdef - blocks to determine which data set you'd want to use before compiling. But if you wanted a different data set, you would need to change (recompile) the executable by changing that define.
Otherwise you would need to compile in C++ as straight C does not support overloaded functions.
Simply put, you just can't. You may be able to include headers before hand based on a condition. Just use #if-def blocks at the top of the file.
But you can't include it like if else:
This is WRONG
if(x == 1)
#include "header1.h"
else
#include "header2.h"
But you can do this at the top of the file:
#if SYSTEM_1
#include "system_1.h"
#elif SYSTEM_2
#include "system_2.h"
#elif SYSTEM_3
#include "system_3.h"
#endif
Or you could just use C++ which does support overloaded functions.
You can do simple metaprogramming by using the macro preprocessing phase. Create a "interface_myFunc.h" with something like
#define FUNCNAME(T) myFunc_ ## T
void FUNCNAME(theType)(theType t);
Create a "implement_myFunc.h" file with something like
void FUNCNAME(theType)(theType t) {
// do something with t
}
and then include this file in another file "myFunc.h"
#define theType toto
#include "interface_myFunc.h"
#undef theType toto
#define theType tutu
#include "interface_myFunc.h"
#undef theType tutu
and similar for the definitions, "myFunc.c"
#define theType toto
#include "implement_myFunc.h"
#undef theType toto
#define theType tutu
#include "implement_myFunc.h"
#undef theType tutu
Modern C, C11, also has ways to create a common interface for all these functions that you create by so-called type generic macros:
#define myFunc(X) \
_Generic((X), \
toto: FUNCNAME(toto), \
tutu: FUNCNAME(tutu) \
)(X)