Extending an API in C in a flexible and unobtrusive way - c

I'm trying to add some additional functionality to an API. However, I'd like these additional functions to be in an external library of mine and not mixed with the original library's code.
The problem comes when I need to access static functions of the mentioned API from my functions. Of course I can't, so the only solution I see is either to copy these functions' code into my API or to make them non-static in the original API. Both are not too good options for me for obvious reasons.
More precisely:
original_api.c
void some_function() -> uses some_helper_function()
static some_helper_function()
my_api_extension.c
void some_extended_function() -> needs to use some_helper_function from original_api.c, but can't
Could you suggest which would be the most flexible way to handle this?
I'd like to point out that it's related to C only, not C++.

Make the functions static.
Create an extern struct with pointers to these functions. Declare it in a separate #include file, available to the extension, but not to the entire world.
Use the struct in your extension.
Something like this:
// in the private header
typedef struct
{
void (*p_myfunc1)(int);
int (*p_myfunc2)(void);
} privateAPI_t;
extern privateAPI_t privateAPI;
// in the library
static void myfunc1(int);
static int myfunc2(void);
privateAPI_t privateAPI = { myfunc1, myfunc2 };
// in the extension
#include <privateAPI.h>
...
privateAPI.p_myfunc1(privateAPI.p_myfunc2());

Related

Static library structs and includes

I'm building up a static embedded C-library, which has an API header file, that lists all available functions. I am not sure about a few thing, that I would like to clarify first before I start implementing it.
First of all, since this is a C-Library for embedded systems, which has hardware FPU, I'm not sure what I should include to calculate the math functions like sinf() etc. Normally I use the hardware specific includes, but that is not avialable in this static C-library, since it can run on some STM32 or even some AVR etc. How can I solve this problem?
Further Lets say I have the files foo.c and foo.h, which provide some hidden functions in the library and then there is the api.h, which can be seen by a user and api.c, which is also hidden. In foo.h are now some structs defined, that I would like to return in a callback to a user. Since this structs are hidden, I'm not sure how I should handle this callbacks. Should I implement a handler in api.c, which maps the structs from the callback from foo.c and pass them to the users callback, where the structs are redefined (with different name) in api.h or are there solutions with less overhead?
When I would define the necessary structs for foo.h in api.h, I would need to include api.h in foo.h, but also foo.h in api.h, that is not a good idea I think.
For the first part of the question, the mathematical operations like sinf should be handled by the C standard library (you should check you specific version for support on your architecture). You can then use the math.h header and its functions, the compiler should then use the FPU to make the floating point computations.
For the second part, the usual way to show the user a hidden structure is with a foward declaration but the user will have to interact with the structure through pointers and access functions.
With you example, say we have four files:
api.h: public header
api.c: source code for functions from the public header
foo.h: library internal header (will not be shipped to the end-user)
foo.c: source code for the internal functions
The api.h is the only interesting file of those (have no changes).
// file: api.h
#ifndef API_H
#define API_H
struct foo; // forward declaration of the foo structure
typedef void (*callback_t)(struct foo*); // typedef for a callback taking a
// struct foo argument
void set_callback(callback_t fn);
#endif
Now we have a type for the callback and the type of the structure given to the callback, but the user cannot interact with the structure itself, since the compiler only knows it exists but does not know its content (nor storage size).
When the user writes a callback like in the below code, the user will need to have some access functions.
#include "api.h"
void user_callback(struct foo* arg) {
// user code here
}
The access functions are usually defined like this:
// in the file api.h or another header that the user has access to
int foo_get_value1(struct foo* arg);
void foo_set_value1(struct foo* arg, int new_value);
and those functions would be implemented in foo.c
struct foo {
int value1;
int value2;
};
int foo_get_value1(struct foo* arg) {
return arg->value1;
}
void foo_set_value1(struct foo* arg, int new_value) {
arg->value1 = new_value;
}
This approach has the added advantage that your foo_set functions can do validity checks to make sure you have appropriate values in your structure.
Please note: I did not add any checks to my access functions to avoid cluttering the code, but when passing a pointer to a function, you should always check it for NULL

Exporting types from private headers via the public header

From what I understand, protection of implementation is a good principle to follow, so when writing a new library I decided to give it a shot. My goal is to protect internally used data types and only export the ones that are absolutely needed for people implementing my library.
Let say I have four files:
library_component.c:
#include "library_component.h"
struct my_data {
int stuff;
};
library_component.h:
// Private header
struct my_data;
library.c
#include "library_component.h"
#include "library.h"
library.h:
// Public header
// Include guards, etc...
typedef struct my_data my_data_type;
In this example library_component.c and library.c would get compiled into a shared library file library.so and installed along with library.h inside the host machine.
What's unclear to me, is how am I supposed to handle the struct my_data situation. I want to export it is as my_data_type. Is it possible to hide the typedef statement from the public header?
If library is the only module exposed to the caller - it is the actual API - then this design is fine. A nosy caller, who for some reason goes to dig up internal header files only used by library, can't do much with it anyway - struct my_data in the header is an incomplete type.
However, a less confusing alternative might be to write library_component.h as:
typedef struct my_data_t my_data_t;
And then use that very same definition in library.h - the type is declared in library_component.h and library.h gets access through it with #include. Then everything will be clear. In library_component.c you would have struct my_data_t { ....
And finally, all functions in library.h should be designed to use my_data_t*, which is a must since the type is incomplete and the caller won't be able to create instances of it.
This design method is known as opaque type/opaque pointers.
You can't hide the typedef from the users of the library because that is the type you want your users to use. This is not a problem in terms of protecting private types however.
The typedef acts as a forward declaration of struct my_data. So users of the library can create pointers to that type but not instances of that type. That protects the implementation details of struct my_data.
For example, your library can include functions like this:
struct my_data *get_new();
void do_something(struct my_data *data);
void do_something_else(struct my_data *data);
void cleanup(struct my_data *data);
These allow users to create instances of the struct via get_new, receiving a pointer to the instance, and to pass that pointer to other library functions to operate on it.

Implementing data hiding access specifiers in C language

Is there is a way to implement access specifiers like "private", "protected" in C language. I came across solutions in the internet about using "static" and "ifdefs" for making a function available only inside certain other functions.
Apart from these, is there any C implementation equivalent of using private and protected access specifiers in C++ classes?
C does not have access specifiers. The only way to hide something from your callers is to not provide its declaration in the header.
You can make it static in the translation unit:
myapi.h
extern int visibleVariable;
void visibleFunction();
myapi.c
int visibleVariable;
static int invisibleVariable;
void visibleFunction() {
...
}
static void invisibleFunction() {
...
}
You can also hide the definition of a struct by placing it in the implementation file. This way all fields of your struct would be private to the translation unit. The drawback to this approach is that the users of your API would be unable to declare variables of your struct's type, so they would need to deal with your struct through pointers.
C has no concept of inheritance, hence there is no equivalent of protected access.
C does not have user definable name spaces or access specifiers. Since you exclude (ab)use of preprocessor, the only way to get compiler error trying to access private parts of "classes" is to not have a .h file which exposes "private" stuff. They can still be put into "private" separate .h files (included by module's or library's own .c files, but not meant to be included from application code), or hidden behind #ifdefs (requiring special define to activate the "private" parts).
One common way to hide things is to use opaque structs AKA opaque pointers. For that approach, the code outside a module or library only has pointer to a struct, but no struct definition. And then it uses functions offered by the module to get an instance, access it, and finally release it.
With this approach, you easily get public interface: the functions you provide in the public .h file, as well as any public support structs which have definition there. The private interface is the code where the full struct definition is visible, and any functions which are not in the public .h file.
Protected access implies inheritance, which usually works very differently from C++, when implemented with C by hand, and which is too broad a subject to cover in this answer. The closest thing to this would probably be to have several .h files, which provide several levels of "public" access, and then it is responsibility of the programmer to not get into problems with them.
The good thing about this approach is, other code using the module does not need to be modified (or even recompiled), if struct is changed. Often struct might even be an union, and then the module's functions would branch based on the actual type, all invisibe from the code using it. Another good thing is, the module can control creation of structs, so it could for example have a pool of structs and avoid using heap, all invisible to the application code. One downside is, you can't have inline functions (because the inline function body in .h file would need the struct definition, which we are trying to hide here), which prevents some nice compiler optimizations in cases where performance is a concern.
Example (untested code written for this answer):
module.h:
// ...other standard header file stuff ...
// forward declaration of struct
struct module_data;
// "constructor" function
struct module_data *module_initialize_data(int value);
// modification function
int module_update_data(struct module_data *data, int adjust);
// "destructor" function
void module_release(struct module_data *data);
module.c
#include "module.h"
// struct definition only in the .c file
struct module_data {
int value;
};
struct module_data *module_initialize_data(int value) {
struct module_data *data = malloc(sizeof(*data));
data->value = value;
return data;
}
int module_update_data(struct module_data *data, int adjust) {
data->value += adjust;
return data->value;
}
void module_release(struct module_data *data) {
free(data);
}
Relevant Wikipedia links for reference:
https://en.wikipedia.org/wiki/Opaque_pointer
https://en.wikipedia.org/wiki/Opaque_data_type

INHERITANCE LIBRARY

I'm interested about this. I have a library house.h, which includes a library roof.h. Also I have a library car.h, which includes a library roof.h.
Library roof.h contains next includes (so far written only using as a relief to explain), e.g.:
//this is only for the house.h`
include tile.h
include beam.h
include form_roof_house.h
//this is only for the car.h
include sheet_metal.h
include form_roof_car.h
include modular.h //, etc.
Now, my questions is, whether there is a way that my library roof.h knows which library is included here, respectively that my library roof.h knows that library house.h is included here. Thanks!
Header files should include header guards ie they will not be included twice. You're alluding to two roof.h files? If they share the same guards the first one will be loaded. C the language without the preprocessor has no knowledge of what's happening as files are included etc before their compiled.
Your program design is flawed, because roof needs to be an "abstract base class" that only know about generic roof stuff and that presents an API. Therefore, roof.h should not include any of those headers. Most importantly there should not be a tight coupling between house roof and car roof, that doesn't make any sense, and those two might not even exist in the same program.
Instead, you need to make two new classes that inherit roof, call them for example roof_house and roof_car. Each of them is including roof.h.
From there, you can implement the program design in many ways, depending on how picky you want to be with the OO part of the design. There's not even a need to use OO design (C programmers are often scared about it) but the above mentioned file dependencies must hold.
Avoiding tight coupling is not specific to OO, it is about applying common sense: avoiding fail-cascading bugs, avoiding maintenance problems etc etc.
One possible design is to implement polymorphism through function pointers:
roof.h
typedef struct roof_t roof_t; // forward declaration
typedef void roof_func_t (const roof_t* roof);
typedef struct
{
roof_func_t* init;
roof_func_t* draw;
} roof_t;
// functions for public interface:
roof_t* roof_create (const roof_func_t* init, const roof_func_t* draw);
void roof_draw (const roof_t* roof);
roof.c
#include "roof.h"
roof_t* roof_create (const roof_func_t* init, const roof_func_t* draw)
{
roof_t* roof = malloc(sizeof(roof_t));
roof->init = init;
roof->draw = draw;
return roof;
}
void roof_draw (const roof_t* roof)
{
roof->draw();
}
roof_house.h
#include "roof.h"
void roof_house_init (const roof_t* roof);
void roof_house_draw (const roof_t* roof);
roof_house.c
#include "roof_house.h"
void roof_house_init (const roof_t* roof)
{
// whatever needs to go here
}
void roof_house_draw (const roof_t* roof)
{
// whatever needs to go here
}
main.c
#include "roof.h"
#include "roof_house.h"
roof_t* my_roof = roof_create(roof_house_init, roof_house_draw);
roof_draw(my_roof);
This is of course just a rough example. Private encapsulation etc needs to be implemented and there might be need for a way for the inherited classes to add their own member variables etc.
Needless to say, each header file should always have header guards.

Interface/Implementation in ANSI C

I'm working on a large project in C, and I want to organize it using interface (.h) and implementation (.c) files, similar to many object-oriented languages such as Objective-C or Java. I am familiar with creating static libraries in C, but I think that doing so for my project is unnecessarily complex. How can I implement an interface/implementation paradigm in ANSI C? I'm primarily using GCC for compilation, but I'm aiming for strict adherence to ANSI C and cross-compiler compatibility. Thanks!
It sounds like you are already doing the right thing: good C code also organizes interfaces in .h-files and implementations in .c-files.
Example a.h file:
void f(int a);
Example a.c file:
#include "a.h"
static void helper(void) {...}
void f(int a) {... use helper()...}
Example main.c file:
#include "a.h"
int main(void) { f(123); return 0; }
You get modularity because helper-functions are not declared in headers so other modules dont know about them (you can declare them at the top of the .c file if you want). Having this modularity reduces the number of recompiles needed and reduces how much has to be recompiled. (The linking has to be done every time though). Note that if you are not declaring helper-functions in the header then you are already pretty safe, however having the static in front of them also hides them from other modules during linking so there is no conflict if multiple modules use the same helper-function-names.
If you are working with only primitive types then that is all you need to know and you can stop reading here. However if your module needs to work with a struct then it gets just a little more complicated.
Problematic example header b.h:
typedef struct Obj {
int data;
}*Obj;
Obj make(void);
void work(Obj o);
Your module wants to pass objects in and out. The problem here is, that internals are leaked to other modules that depend on this header. If the representation is changed to float data then all using modules have to recompile. One way to fix this is to only use void*. That is how many programs do it. However that is cumbersome because every function getting the void* as argument has to cast it to Obj. Another way is to do this:
Header c.h:
typedef struct Obj*Obj;
Obj make(void);
void work(Obj);
Implementation c.c:
#include "c.h"
typedef struct Obj {
int data;
}*Obj;
The reason why this works is, that Obj is a pointer (as opposed to a struct by value/copy). Other modules that depend on this module only need to know that a pointer is being passed in and out, not what it points to.
You must read something about OOP with non OOL such like http://www.cs.rit.edu/~ats/books/ooc.pdf.
But, doing such you will never have strong OOP typing.
Please do yourself a favor and read C Interfaces and Implementations: Techniques for Creating Reusable Software
Here is a repository of mine that holds some libs written in C using the pattern of interfaces & implementation described in the book.

Resources