I'm writing a function that should have two versions: a debug version and non-debug version. Which one of the two functions is used should be decided by the caller.
I want something like this:
caller.c
// comment out the following line when not necessary anymore
#define MY_FUNC_DEBUG
#include "my_func.h"
// some code that calls my_func()
my_func.h
void my_func(void);
my_func.c
void my_func()
{
// lots of code
#ifdef MY_FUNC_DEBUG
// debug code
#endif
// more code
}
This obviously won't work, because my_func.c is compiled separately from caller.c, therefore it can't know what macros it defined.
How can I make this work easily? I wouldn't want to write the two versions of my_func separately, because they share most of their code.
Assuming that you are using gcc, this problem can be easily solved by defining the macro at compile time via the -D option in both files.
In your example you could compile both files using -D MY_FUNC_DEBUG when you want the debug code to be activated and nothing otherwise. There is not need for defining MY_FUNC_DEBUG in caller.c.
Make the debugging code in my_func() switchable at run-time.
my_func.h
#ifndef MY_FUNC_H_INCLUDED
#define MY_FUNC_H_INCLUDED
extern int my_func_debug(int level);
extern void my_func(void);
#endif
my_func.c
#include "my_func.h"
static int debug = 0;
int my_func_debug(int level)
{
int rv = debug;
debug = level;
return rv;
}
void my_func(void)
{
...
#ifdef MY_FUNC_DEBUG
if (debug)
...debug...
#endif
...
}
caller.c
void consumer(void)
{
int old = my_func_debug(9);
my_func();
my_func_debug(old);
}
Discussion
The outline code means that you can have one copy of the source for my_func.c, but it can be compiled with debug included, or with it excluded. The consumer code (caller.c) can request the level of debugging it wants, but whether that does anything useful depends on whether the copy of my_func.o (my_func.obj on Windows) was compiled with debug included. You get one source file; you get to choose which variant of the object file is included in the program with caller.o. And at runtime you can request debugging.
Note that my_func_debug() is unconditionally defined; it just doesn't do anything very useful if the my_func.c code is not compiled with -DMY_FUNC_DEBUG.
Related
We have a repo that contains library functions for example (gcc is used to compile and link).
//print.h
#ifndef __PRINT_H_
#define __PRINT_H_
#define MAX_ARRAY 10
void print_hex(int cal[]);
#endif
// print.c
#include <stdio.h>
void print_hex(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf("%i\n",val[I]);
}
}
The above is compiled into a libprint.a.1.0.0. My app is then compiled using this library
//main.c
#include "print.h"
int main(int argc, int arg[]) {
int vals[MAX_ARRAY];
memset(vals,8,MAX_ARRAY*sizeof(int));
print_hex(vals);
return 0;
}
And everything is fine and works (assuming have typed the above out correctly). But then someone decides to make a change in the library where someone Makes the following change.
//print.h
...
#define MAX_ARRAY 50
...
The library is recompiled to libprint.a.1.1.0
This new static library is now used when compiling and linking our main.c. However, the new print.h was not copied to the include directory so the main.c is using an old print.h where MAX_ARRAY is smaller.
Now in this case we might get any behaviour as the print function runs off the end of the passed in array. As a user of the library there is no way to necessarily know that the header file is wrong until I compile and run the application, or perhaps even hours of running when the program starts to go crazy.
What is the standard way to avoid this issue?
Is there a way to add a version to a header file to ensure the correct library is linked?
I realise I could do this by creating a new function in print.c called get_version(), and use that in main.c to check against some defines in print.h to ensure veracity but I was wondering if there was a way without the user application having to specifically check library and header versions at run time.
Yes. And don't do it.
The libfuse library uses a macro FUSE_USE_VERSION that should be defined by the client to differentiate between different versions. Internally it works similar to feature_test_macros.
So in your library it would look like:
print.h:
#ifndef __PRINT_H_
#define __PRINT_H_
#if PRINT_USE_VERSION == 1
#define MAX_ARRAY 10
void print_hex_version_1(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_1(val);
}
#elif PRINT_USE_VERSION == 2
#define MAX_ARRAY 50
void print_hex_version_2(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_2(val);
}
#else
#error unknown PRINT_USE_VERSION
#endif
#endif
print_version_1.c:
#define PRINT_USE_VERSION 1
#include <stdio.h>
void print_hex_version_1(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(“%i\n”,val[I]);
}
}
print_version_2.c:
#define PRINT_USE_VERSION 2
#include <stdio.h>
void print_hex_version_2(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(“%i\n”,val[I]);
}
}
Or similar, hope you'll you get the idea. Using this method you can distribute all possible versions of your library at once. And clients can link against multiple versions of your library. Which ends up being spaghetti code, unstable, unreliable, unfixable and unmaintainable.
On a global scale, it makes no sense. Just create a api that isn't dependent on a macro definition and take the array size as an argument. Check if the size of the array is equal to some predefined value and notify your client with error code that he did something wrong.
Alongside main.c file, I have following my_custom_data_structure.c file in my project. My my_custom_data_structure.c file contains a lot of variables, functions, etc.
I am using #include "my_custom_data_structure.c" directive in main.c.
Problem
I would like to import only single function called foo from my_custom_data_structure.c. I don't need all the variables and functions, which are declared in my_custom_data_structure.c file.
Any insights appreciated.
File structure
-
|- main.c
|- my_custom_data_structure.c
Content of my_custom_data_structure.c
#include <stdio.h>
int DELAY = 20;
int SPEED = 7;
char GRANULARITY_CHAR = 'g';
unsigned int RANGE = 3;
void foo(){
// TODO: In future, this function will print SPEED.
printf("foo works!");
}
/*
The rest of this file is filled by a lot
of code, which is not needed for main.c
*/
Content of main.c
#include <stdio.h>
#include "my_custom_data_structure.c"
int DELAY = 3;
int main(){
foo();
printf("Delay is %d", DELAY);
return 0;
}
UPDATED: Added working example
The usual way is to compile them separately. So you have your main.c, and your extra.c, and you should create a extra.h (and include it in main.c).
In this extra.h, put in declarations for anything that is to be exported from your extra.c file.
For example any functions that should be available to other files. All other functions should be declared/defined only in your extra.c as static, so that they are not available as symbols to be linked when main.c is compiled.
Normally, you don't include source files (.c) inside other source files (or inside headers). It's possible (and occasionally necessary), but it isn't usual.
Unless you've designed the my_custom_data_structure.c to allow you to specify which functions are to be compiled, you get everything in the file. For example, you could use:
#ifdef USE_FUNCTION1
void function1(void *, …)
{
…
}
#endif /* USE_FUNCTION1 */
around each function, and then arrange to
#define USE_FUNCTION1
before including the source, but that's not usually a good way of working. It's fiddly. You have to know which functions you use, and which other functions those need, and so on, and it is vulnerable to changes making the lists of USE_FUNCTIONn defines inaccurate. Of course, the source code might have blocks of code like:
#ifdef USE_FUNCTION1
#define USE_FUNCTION37
#define USE_FUNCTION92
#define USE_FUNCTION102
#endif /* USE_FUNCTION1 */
so that if you say you use function1(), it automatically compiles the other functions that are required, but maintaining those lists of definitions is fiddly too, even when the definitions are USE_MEANINGFUL_NAME instead of a number.
Create a header (my_customer_data_structure.h) declaring the functions and any types needed, and split the implementation into many files (mcds_part1.c, mcds_part2.c, …).
Compile the separate implementation files into a library (e.g. libmcds.a), and then link your program with the library. If it's a static library, only those functions that are used, directly or indirectly, will be included in the executable.
I am using Check framework do to unit testing of my C code, and I couldn't find a proper way to test the static methods.
My work around, is not ideal at all and would like if someone can point me in the right direction on how to do it properly. My work around is simply by add #ifdef macro that changes the static methods to extern in case I pass -D DEBUG at compile time.
In the source file
#ifdef DEBUG
unsigned ds_roundup_to_prime (const unsigned bsize) {
#else
static inline unsigned ds_roundup_to_prime (const unsigned bsize) {
#endif
And in the header file I do
#ifdef DEBUG
unsigned ds_roundup_to_prime (const unsigned bsize);
#endif
Ideally source code shouldn't change to cater for unit tests. Unit-test framework, should must be capable of testing the source code as it will look in production.
Thanks
It's debatable whether or not static functions should be tested, as they aren't part of the public API.
I test static functions by including the unit-under-test, rather than linking against it:
foo.c (Unit under test)
static int foo(int x)
{
return x;
}
/* ... */
test_foo.c
#include "foo.c"
void test_foo(void)
{
assert( foo(42) == 42 );
}
int main(void)
{
test_foo();
}
Compile just that test:
$ gcc -Wall -Werror -o test_foo test_foo.c
$ ./test_foo
I test static functions in the following manner.
I have a header file called utility.h. It has the following definition:
#ifdef UNIT_TEST
#define UTILITY_STATIC(DECLARATION) extern DECLARATION; DECLARATION
#else
#define UTILITY_STATIC(DECLARATION) static DECLARATION
#endif
Every source file that has functions that are to be tested are declared as such:
#include "utility.h"
UTILITY_STATIC(void function(void));
UTILITY_STATIC(void function(void))
{
}
I have an additional header file (e.g. test_helper.h), used in the unit test executable, that has the line:
extern void function(void);
In this way, tests have access to function whereas source files that don't define UNIT_TEST do not.
Note
This can be used for static variables as well.
I'm wondering whether a C file can be both included in another script (through a header file), and also run independently (by having its own main function). That is, the C file can be included to provide its functions to another C script, but can also itself be directly ran to provide some alternate functionality.
For example, a python script can do this;
def functionsToBeImported():
# code to be run by an importing script
pass
if __name__ == '__main__':
# code to be run by this script independently
pass
This code can be imported (import ABOVESCRIPT) by another python file to give access to functionsToBeImported, or independently run (python ABOVESCRIPT.py) to execute the code within the if block.
I've attempted to do this in C via myScript.c:
#include "myScript.h"
void functionsToBeImported() {
}
int main (int narg, char* varg[]) {
}
myScript.h:
#ifndef MY_SCRIPT_H_
#define MY_SCRIPT_H_
void functionsToBeImported();
#endif // MY_SCRIPT_H_
but trying to include this in anotherScript.c:
#include "myScript.h"
int main (int narg, char* varg[]) {
functionsToBeImported();
}
and trying to compile via
gcc -std=c99 -c myScript.c
gcc -std=c99 -c anotherScript.c
gcc -std=c99 -o anotherScript anotherScript.o myScript.o -lm
gives be a compilation error
duplicate symbol _main in:
myScript.o
anotherScript.o
How can I achieve this 'double-use' script?
You cannot link both anotherScript.o and myScript.o, but you could do something like this:
#define main ignored_main
// Include myScript.c, not myScript.h
#include "myScript.c"
#undef main
int main (int narg, char* varg[]) {
functionsToBeImported();
}
I have actually seen things like this in code very widely used in production, although I cannot recommend this style (but it is sometimes a tempting shortcut).
Another option is to include the main function only if a preprocessor macro is defined, like this (in myScript.c):
#include "myScript.h"
void functionsToBeImported() {
}
#ifdef USE_MAIN
int main (int narg, char* varg[]) {
}
#endif // USE_MAIN
This is similar in spirit to the Python approach. But again, you will have to compile this file twice into separate object files.
Note: C files are not scripts.
You cannot have two main functions, as C is a procedural language, meaning you must do one thing at a time (unless you are multithreading, in which case you would still only have one main function).
HOWEVER, there is something quite close to replicating what you want. What you can do is first, write the main method only in the first included file. In the main file, set the atexit() function from the C stdlib.h file (which calls another function at the end of main) to a main2() function (make sure that there is a prototype of each main#() function in the first header as well, and implement all of the functions eventually). Define a macro called MAIN_ONE in the function with the original main. In each consecutively included file, implement the next main and create a macro so that checks to see if the function was implemented can be made. However, the natural, and most efficient way to make a program in C is to just have one main function.
Example:
//In first included file
#include //Some IDEs automaticaly include this. This must be included since it is where the atexit() function resides
#define MAIN_ONE
void main2(); //For the moment, this is only a prototype.
void main3();
//etc. Until you have created the maximum number of main functions that you can have
int main() {
//do something
atexit(main2); // This will execute the function main1() once main returns
//All "fake" mains must be void, because atexit() can only receive void functions
}
//In second included file
#if defined(MAIN_THREE) //start from the maximum number of main functions possible
#define MAIN_THREE //The define is for preprocessor-checking purposes
void main4() {
atexit(main5);
}
#elif defined(MAIN_TWO) //start from the maximum number of main functions possible
#define MAIN_TWO
void main3() {
atexit(main5);
}
//Keep repeating until you reach #ifdef(MAIN_ONE)
#endif
//At the bottom of the main C file
//This is done in order to make sure that all functions have actually been created and reside in memory so that an error does not occur
//(all unused functions are initialized with an empty function here)
#if defined(MAIN_THREE) //start from the maximum number of main functions possible
//Do nothing because if MAIN_THREE is defined when main4(), the last main in my example has already been implemented.
//Therefore, no more functions need to be created
#elif defined(MAIN_TWO) //start from the maximum number of main functions possible
#define MAIN_TWO //Since more mains after main2 can be present, another macro for future checks needs to be defined
void main3() {
}
//Keep repeating until you reach #ifdef(MAIN_ONE)
#endif
I'm writing a C program that uses a custom logging function to debug my program. Whenever I compile my program as a release version, I want all of my logging functions to be stripped from the code so it won't show up if someone tries to disassemble it.
Take the following example:
#include <stdio.h>
void custom_logging_function(char* message)
{
// Do something here
}
int main()
{
custom_logging_function("Hello world"); // This call should be removed.
return 0;
}
How could I make it so that the custom_logging_function and it's arguments aren't compiled into my program without having to write include guards everywhere throughout my code? Thank you
You can use pre-processor flags, for example:
#include <stdio.h>
#ifdef DEBUG
void custom_logging_function(char* message)
{
// Do something here
}
#else
#define custom_logging_function(x) ((void) 0)
#endif
int main()
{
custom_logging_function("Hello world"); // This call should be removed.
return 0;
}
With this code you will have to tell the "debug" target to define DEBUG, if you want to define something specifically for the "release" target you can replace #ifdef DEBUG with #ifndef NDEBUG and add the NDEBUG flag to the "release" definitions.
Edit:
Changed #define custom_logging_function(x) 0 to #define custom_logging_function(x) ((void) 0) inspired by #JoachimPileborg his answer.
Assuming you only want the logging calls to happen in a debug-build of your application, and not the release build you send to customers, you can still use the preprocessor and conditional compilation for it. It can be made vert simple though by using macros instead of having checks at every call.
Something like this in a heder file:
#ifdef _DEBUG
void custom_logging_function(char* message);
#else
# define custom_logging_function(message) ((void) 0)
#endif
You could use an empty macro body for the release-macro, but that can cause some compilers to give "empty statement" warnings. Instead I use an expression casted to void (to tell the compiler that the result of the expression will not be used). Any smart compiler will not include the expression after optimization.