Best way to abstract away an init function? - c

I am making a low level library that requires initialization to work properly which I implemented with a init function. I am wondering if there is a way to make the init call be called once the user calls a library function ideally without:
Any overhead
No repeated calls
No exposed global variables. (my current solution does this, which I don't quite like)
my current solution as per comment request:
bool isinit = 0;
void init()
{
isinit = 1;
// init code
}
void lib_function()
{
if(!isinit) init();
// function code
}
The compiler seems to be smart enough (using -0fast on gcc) to not make that comparison each time a lib_function is called, but this still exposes a global variable which I don't like.

Best way to abstract away an init function?
Surely your library has some state. Typically, a library exposes functions that work on a specific structure. Do not use global variables - do not write spaghetti code. Expose the structure that holds the state of your library, and make all functions of your library take a pointer to the structure as an argument. Use a namespace - prepend all exported symbols with a prefix. An init function is just like int lib_init(struct lib_the_struct *t); - it will be self-understandable that users need to initialize the structure with that function before use. For example: fopen(), pthread_create.
Write an init function in your library. Write clear documentation stating, that the user of your library has to call the function once before calling any other function. For example: https://curl.se/libcurl/c/curl_global_init.html .

If you're happy with a solution that is a common extension rather than part of the C standard, you can mark your init function with the constructor attribute, which ensures it will be called automatically during program initialization (or during shared library load if you eventually end up using that).

I would fix this with assert so that the if will dissappear in release build and if you forget to call the init_function somewhere you get the error while developing.
Also turn isinit into a static so every library can have its own variable with the same name.
#include <assert.h>
#ifndef NDEBUG
static int isinit = 0;
#endif
void lib_function()
{
assert(isinit && "library: init not called");
}

There will be overhead if you run if(!isinit) init(); each time you call a function. At least an extra branch.
As for removing global variables, do in your example but static bool isinit = 0;. This reduces the scope of the variable to the local translation unit (.c file and all .h files it includes). It's no longer "global". Note that this isn't ideal in multi-threaded scenarios - you will have to protect the variable with a mutex then.
Overall though, what you are trying to do isn't a good idea. It is very common convention for C libraries to have an init function and the user of the library is expected to call it before calling anything else or they are to blame, not your library. Naturally you have to make this clear to them with source code documentation. It is common to have a list of prerequisites in source code comments together with every function declaration placed in the header file of the library.

Related

Resolving function name conflicts by using static

Say we have a library that defines the following internally used function skip_comments, that is used only by the translation unit it is defined in
void skip_comments(...)
{
}
void another_function()
{
skip_comments(...) //calls the above function --- (1)
}
Now this library is used by another process which also has a function with the same name skip_comments.
This will cause a function name conflict between the library function vs the function defined in the process. So at the point (1) I might expect it to call the process's function instead of the library function which clearly is a bug.
As a possible fix, I made the skip_comment function static and now the bug seems to be fixed. But I'm not sure if this is a proper fix
My question is, would defining the skip_comment as static ensure that at (1) such a name conflict will not occur? ie.
static void skip_comments(...)
{
}
void another_function()
{
skip_comments(...) // will it always call the internal function?
}
Or the only solution is to make sure we define a unique name for functions such as adding prefixes?
Declaring a function as static means that it will only be accessible by the translation unit where it is declared. (Translation unit meaning the .c file and all .h files included by that .c file.)
So yes, declaring it as static will solve your name conflicts. Given that you do this consistently everywhere and not just in one file.
However, it is good practice to prefix all identifiers based on the module where they belong, so that is perhaps the best solution regardless.

How static init and exit functions in a module are called outside the file by the kernel?

I am reading LDD3 and had a doubt regarding the usage of static storage class in the __init and __exit function calls.
http://static.lwn.net/images/pdf/LDD3/ch02.pdf
"Initialization functions should be declared static, since they are
not meant to be visible outside the specific file; there is no hard
rule about this, though, as no function is exported to the rest of the
kernel unless explicitly requested"
But then the kernel is able to use init and exit function using insmod and rmmod system calls. If static functions are functions that are only visible to other functions in the same file, then how is the kernel able to use the __init and __exit functions defined static in our module?
Static function in one translation unit can be exported through back-doors like function pointers. The dynamic linking uses the same approach.
In your driver code you must also be writing
module_init(__init_function_name__) and module_exit(exit_function_name).
You may see how these macros are implemented.
Technically in C, by exporting function pointer of static function in one file and calling them from another file using extern function pointer is possible. And many such framework like Linux kernel are doing the same.
module_inint(your_func);
module_init is macro which expands such that your your_func's function pointer is getting added in one array. Which getting called at boot up time or module loading time.
A great explannation about module_init() is at https://stackoverflow.com/a/18606561/775964

Removing functions included from a header from scope of the next files

In my project we are heavily using a C header which provides an API to comunicate to an external software. Long story short, in our project's bugs show up more often on the calling of the functions defined in those headers (it is an old and ugly legacy code).
I would like to implement an indirection on the calling of those functions, so I could include some profiling before calling the actual implementation.
Because I'm not the only person working on this project, I would like to make those wrappers in a such way that if someone uses the original implementations directly it should cause a compile error.
If those headers were C++ sources, I would be able to simply make a namespace, wrap the included files in it, and implement my functions using it (the other developers would be able to use the original implementation using the :: operator, but just not being able to call it directly is enough encapsulation to me). However the headers are C sources (which I have to include with extern "C" directive to include), so namespaces won't help me AFAIK.
I tried to play around with defines, but with no luck, like this:
#define my_func api_func
#define api_func NULL
What I wanted with the above code is to make my_func to be translated to api_func during the preprocessing, while making a direct call to api_func give a compile error, but that won't work because it will actually make my_func to be translated to NULL too.
So, basically, I would like to make a wrapper, and make sure the only way to access the API is through this wrapper (unless the other developers make some workaround, but this is inevitable).
Please note that I need to wrap hundreds of functions, which show up spread in the whole code several times.
My wrapper necessarily will have to include those C headers, but I would like to make them leave scope outside the file of my wrapper, and make them to be unavailable to every other file who includes my wrapper, but I guess this is not possible in C/C++.
You have several options, none of them wonderful.
if you have the sources of the legacy software, so that you can recompile it, you can just change the names of the API functions to make room for the wrapper functions. If you additionally make the original functions static and put the wrappers in the same source files, then you can ensure that the originals are called only via the wrappers. Example:
static int api_func_real(int arg);
int api_func(int arg) {
// ... instrumentation ...
int result = api_func_real(arg);
// ... instrumentation ...
return result;
}
static int api_func_real(int arg) {
// ...
}
The preprocessor can help you with that, but I hesitate to recommend specifics without any details to work with.
if you do not have sources for the legacy software, or if otherwise you are unwilling to modify it, then you need to make all the callers call your wrappers instead of the original functions. In this case you can modify the headers or include an additional header before that uses #define to change each of the original function names. That header must not be included in the source files containing the API function implementations, nor in those providing the wrapper function implementations. Each define would be of the form:
#define api_func api_func_wrapper
You would then implement the various api_func_wrapper() functions.
Among the ways those cases differ is that if you change the legacy function names, then internal calls among those functions will go through the wrappers bearing the original names (unless you change the calls, too), but if you implement wrappers with new names then they will be used only when called explicitly, which will not happen for internal calls within the legacy code (unless, again, you modify those calls).
You can do something like
[your wrapper's include file]
int origFunc1 (int x);
int origFunc2 (int x, int y);
#ifndef WRAPPER_IMPL
#define origFunc1 wrappedFunc1
#define origFunc2 wrappedFunc2
#else
int wrappedFunc1(int x);
int wrappedFunc2(int x, int y);
#endif
[your wrapper implementation]
#define WRAPPER_IMPL
#include "wrapper.h"
int wrapperFunc1 (...) {
printf("Wrapper1 called\n");
origFunc1(...);
}
Your wrapper's C file obviously needs to #define WRAPPER_IMPL before including the header.
That is neither nice nor clean (and if someone wants to cheat, he could simply define WRAPPER_IMPL), but at least some way to go.
There are two ways to wrap or override C functions in Linux:
Using LD_PRELOAD:
There is a shell environment variable in Linux called LD_PRELOAD,
which can be set to a path of a shared library,
and that library will be loaded before any other library (including glibc).
Using ‘ld --wrap=symbol‘:
This can be used to use a wrapper function for symbol.
Any further reference to symbol will be resolved to the wrapper function.
a complete writeup can be found at:
http://samanbarghi.com/blog/2014/09/05/how-to-wrap-a-system-call-libc-function-in-linux/

Move an interrupt handler and variables from main to a include file

I've a newbie question about how to correctly move an interrupt handler to an include file. I've a SysTick handler in my main.c file defined in this way:
volatile int systick_timer_counter = 0;
void SysTick_Handler(void) {
systick_timer_counter++;
}
I use this systick_timer_counter, that is increased every 10 ms, to trigger some checks after some time has passed, then reset it.
What I want is to use this systick_timer_counter also inside some functions that aren't in my main.c file, but in another function's .c file. So I want to create a file called systick_counter to include where I need to use it.
What I'm asking is, how should I do this in correct way? I can just create a .c file and place variable and interrupt header inside it, or should I add something more or change variable definition?
It sounds like you mean you want to have a global variable defined in
one module (source file) that’s accessible from other modules.
Assuming I’ve interpreted your question correctly, yes, that can be done
by using the extern keyword. However, it would be irresponsible of me
not to say that using globals unnecessarily is bad practice. It
results in hard-to-maintain code, because an extern global might be
changed from anywhere in the code base. You want to limit scope and
visibility of your identifiers as much as you can.
In this instance, I would recommend that you instead keep
systick_timer_counter local to the module in which it’s defined, and
use functions in that module to access it. It’s like defining a class
with methods, in a language that doesn’t have explicit classes. Doing it
this way, other modules can’t change the value except by calling
reset_systick().
int systick_timer_counter = 0;
void reset_systick()
{
systick_timer_counter = 0;
}
void SysTick_Handler()
{
systick_timer_counter++;
}
int return_systick()
{
return systick_timer_counter;
}
It's also a good idea to add the static keyword to variables that you want to only be accessible from within the file.
static int systick_timer_counter = 0;

How to test a static function

As applying unit-test to some C code, we run into a problem that some static function can not be called at the test file, without modifying the source code. Is there any simple or reasonable way to overcome this problem?
I have a test harness. In dire cases - like trying to test a static function, I use:
#include "code_under_test.c"
...test framework...
That is, I include the whole of the file containing the function under test in the test harness. It is a last resort - but it works.
Can you give more information as to why you can't call the function?
Is it not available because it's private to a .c file? If so, you're best bet is to use conditional compilation that allows for access to the function in order to allow for other compilation units to access it. For example
SomeHeaderSomewher.h
#if UNIT_TEST
#define unit_static
#else
#define unit_static static
#endif
Foo.h
#if UNIT_TEST
void some_method
#endif
Foo.cpp
unit_static void some_method() ...
For unit tests, we actually have the test code within the source file itself and we conditionally compile it in when testing. This gives the unit tests full access to all functions and file-level variables (static or otherwise).
The unit tests themselves are not static - this allows us to call the unit tests from a single super-test program which unit tests all compilation units.
When we ship the code, we conditionally compile out the unit tests but this isn't actually necessary (if you want to be certain you're shipping exactly the same code you tested).
We've always found it invaluable to have the unit tests in the same place as the code you're testing since it makes it more obvious that you need to update the tests if and when the code changes.
No - you cannot directly test a static function without modifying the source at least a little (that is the definition of static in C - that it cannot be called from a function in a different file).
You could create a separate function within the test file that just calls the static function?
For example:
//Your fn to test
static int foo(int bar)
{
int retVal;
//do something
return retVal;
}
//Wrapper fn
int test_foo(int bar)
{
return foo(bar);
}
We usually don't test our static functions directly, but rather ensure that the logic they perform is adequately tested by different tests of the calling function.
static functions are essentially helper functions to the public (i.e. exposed) functions. So IMO, your unit tests should call the public interface with inputs that exercise all the paths in the static function.
The output (return values / side effects) of the public function should be used to test the effect of the static.
This means you need to have appropriate stubs to 'catch' these side effects. (e.g. if a function calls file IO, you need to provide stubs to override these file IO lib functions). The best way to do this by making each test suite a seperate project/executable and avoid linking to any external lib functions. You can mock even C functions, but it's not worth the effort.
Anyway, this is the approach I've used so far and it works for me. Good luck
#define static
This is a very bad idea. If you have a variable declared local to a function, it changes the behavior of the function. Example:
static int func(int data)
{
static int count = 0;
count += data;
return count;
}
You could call the function from the unit test, as func() would be exported, however the basic functionality of the code would be modified.
--kurt
If you are under Unix environment you can include in test file additional header yourheader_static.h with declarations of your static functions and translate obj file code_under_test.o through objdump --globalize-symbols=syms_name_file to globalize local symbols. They will be visible as if they are non-static functions.
Just to add to the accepted answer by Jonathan Leffler, and elaborate on other's mention of a wrapper function:
Create a test source file, as in test_wrapper_foo.c, where foo.c is the original.
In test_wrapper_foo.c:
#include "foo.c"
// Prototype
int test_wrapper_foo();
// wrapper function
int test_wrapper_foo() {
// static function to test
return foo();
}
Assuming that the static function foo in foo.c has prototype: int foo(void);
build test_wrapper_foo.c through your makefile instead of foo.c (note that this will not break any dependencies on functions in foo.c by other external functions)
In your unit test script, call test_wrapper_foo() instead of foo().
This approach leaves the original source intact, while giving you access to the function from your test framework.
You could add a non-static function to call the static function, then call the non-static function.
static int foo ()
{
return 3;
}
#ifdef UNIT_TEST
int test_foo ()
{
if (foo () == 3)
return 0;
return 1;
}
#endif
If you're using Ceedling and trying to use the #include "code_under_test.c" method, the test build will fail because it will automatically try to build "code_under_test.c" once when #included and also because it's the target of the test.
I've been able to get around it by a slight modification to the code_under_test.c code and a couple of other changes. Wrap the whole code_under_test.c file with this check:
#if defined(BUILD)
...
#endif // defined(BUILD)
Add this to your test harness:
#define BUILD
#include "code_under_test.c"
Add the BUILD define to your Makefile or project config file:
# Makefile example
..
CFLAGS += -DBUILD
..
Your file will now build from your environment and when included from your test harness. Ceedling will now not be able to build the file a second time (ensure your project.yml file does NOT define BUILD).
All the above suggested answers (except a few) suggest conditional compilation which requires modification to source. As such that shouldn't be an issue, it just would add clutter (just for testing). Rather you can do something like this.
Say your function to be tested is
static int foo(int);
You make another header file called testing_headers.h which will have the contents -
static int foo(int);
int foo_wrapper(int a) {
return foo(a);
}
Now while compiling your c file for testing you can force include this header from the compiler options.
For clang and gcc the flag is --include. For Microsoft C compiler it is /FI.
This will require absolutely 0 change to your c file and you will be able to write a non static wrapper to your function.
If you don't want a non static wrapper, you can also create a non static global function pointer initialised to foo.
You can then call the function using this global function pointer.
There are 2 ways to do this.
Include the c source file into the unit testing source file, so the static method now is in the scope of unit testing source file and callable.
Do a trick:
#define static
in the head of unit testing source file.
It will convert keyword static to "nothing" or I can say, it removes static from your c source code.
In some unit testing tool, we can use config option "pre-processor" to do this trick, just put in the config:
static=
The tool willl convert all static keyword to "nothing"
But I must say, using these ways make the static method (or variable) loses the specific meaning of it.

Resources