Are there any conventions for seperating the public interface headers and internal headers? I've looked at some libraries and see that mostly the internal headers are in the src directory named something-internal.h and the public headers are in the include directory. I was thinking of something like this:
(xyz is the library name)
include/xyz/something.h (public interface)
struct something;
void do_something(struct something *s);
src/something.h (internal header)
/* include public header */
#include "xyz/something.h"
/* struct definition in internal header for opaque struct */
struct something { int x, int y };
src/something.c
/* not xyz/something.h, but the private header in src/ */
#include "something.h"
void do_something(struct something *s) {
/* function definition */
}
So note that I don't use the -internal suffix, because in my opinion if the header is in the src directory it's internal. Is this clear enough for, for example, new contributors? Or should the -internal suffix be added for clarity?
`
I think what you suggest is perfectly fine. The linux kernel uses a similar layout with the public sched.h under include/ and the private sched.h under kernel/sched – Frederik Deweerdt
Related
I have a static function in a source file that is used by other functions in that same source file. Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files? Example:
/* foo.c */
#include "foo.h"
/* exported function; calls g */
void f(void) {
g();
}
static
void g(void) {
/* do something... */
}
/* foo.h */
void f(void);
void g(void);
/* main.c */
#include "foo.h"
int main(void) {
f();
}
Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files?
No. Consider the conflict the other source files would have if they had a function/object/macro of the same name.
Even without conflict, an "unused function" warning may occur. #Adrian Mole
By putting static void g(void) in the .h file, it adds an unnecessary potential name conflict.
Simply declare/define that static function at the top of the .c in which it is used.
Is it fine to put the declaration for that static function in the
header file, even though that header file will be included into other
source files?
No. becuse it does not make any sense. and why?
In C, functions are global by default. Unlike global functions in C, access to static functions is restricted to the file where they are declared! Therefore, when we want to restrict access to functions, we make them static.
Another reason for making functions static can be reuse of the same function name in other files. so declaring them static in the header file can cause to name collisons in other source files.
In header files we declare our API functions those we want to expose only. in c files we declare usually auxilary functions as static functions for restricting the scope of those aux functions to the c file only
I'm trying to implement a framework, where I would need to declare (in .h file) the list of available "drivers" (struct variables) which would be defined in specific .c modules. As the list would probably grow in the future I would like to have it all in one place in the .h file to keep it easily extensible.
E.g. let's have "driver.h"
typedef struct driver {
int id;
char name[10];
int(*init)();
void (*deinit)();
int (*doTheJob)(int);
} driver_t;
#define DRIVERLIST driver1, driver2, driver3
#define DRIVERS extern driver_t DRIVERLIST;
DRIVERS
Then the specific drivers (driver1, driver2, driver3) would be defined in dedicated modules.. e.g. driver1.c, driver2.c .. etc...
But then I would like to have a module e.g. manager.c where I would like to define the array of available drivers as declared in driver.h so that I'm able to iterate the array and get the drivers for usage in other parts of the framework..
So in manager.c I would need something like:
driver_t drivers[MAX_DRIVERS] = {DRIVERS}
But obviously it does not compile this way..
The main idea is to edit only driver.h when I need to add declaration for additional driver in the future and then just implement it in dedicated module, whithout the necessity to edit e.g. manager.c or other parts of the framework..
Do you have any idea, how to implement such mechanism in c?
In C you can't initialize an array with copies of some objects (in C++ can but it is not good practice because they are copies and will be changed independently with original objects).
drivers array should contain pointers to original objects. I suggest something like
/* driver.h */
typedef struct driver {
int id;
char name[10];
int(*init)();
void (*deinit)();
int (*doTheJob)(int);
} driver_t;
#define MAX_DRIVERS 10
#define DRIVERLIST driver1, driver2, driver3
#define DRIVERS_INIT {&driver1, &driver2, &driver3}
#define DRIVERS extern driver_t DRIVERLIST;
DRIVERS
/* manager.c */
#include "driver.h"
/* ... */
driver_t * drivers[MAX_DRIVERS] = DRIVERS_INIT;
Manager code will use drivers[i]->id instead of drivers[i].id.
The proper way to do this in C is to immediately get rid of all extern-spaghetti with globals.
Instead you could put your struct definition inside driver.h and in driver.c initialize it through a "constructor":
// driver.c
#include "driver.h"
#include "specific_driver_x.h"
void driver_init (driver_t* driver)
{
driver->init = specific_driver_init;
driver->doTheJob = specific_driver_job;
}
For professional code, this can be further improved with the concept of "opaque type" as explained here, to achieve private encapsulation (and if needed polymorphism). In which case the struct definition can be (partially) hidden in driver.c and the constructor also handles memory allocation.
I think I found a solution. I took the inspiration from the rtl_433 project https://github.com/merbanan/rtl_433/blob/master/include/rtl_433_devices.h where they defined something similar for the devices declarations.
So it should be in header file:
/* driver.h */
#define DRIVERS \
DECL(driver1) \
DECL(driver2)
#define DECL(name) extern driver_t name;
DRIVERS
#undef DECL
And then in module:
/* driver.c */
driver_t* drivers[] = {
#define DECL(name) &name,
DRIVERS
#undef DECL
};
I have several header files in a library: header1.h, header2.h...
I also have a general header file for the library: mylib.h
I want the user to import the main.h file and get access to only some of the functions in the other header files.
For example, in the library:
// header1.h
void a(void);
void b(void);
-
// mylib.h
// I can't use this:
#include "header1.h"
// because it would make b function visible.
// Link to function a ????????
And in my main program:
// main.c
#include "mylib.h"
int main(void) {
a(); // Visible: no problem
b(); // Not visible: error
return 0;
}
Separate function prototypes into different headers, depending on whether they should be "visible"*1 or not (but be "internal").
header1_internal.h
header1.h
header2_internal.h
header2.h
...
Include into the *_internal.h headers the related *.h header.
Include the *_internal.h headers into your lib's related modules.
Do not include any *_internal.h into mylib.h.
*1: Please note that even when not providing a prototype this way the user might very well craft his/her own prototype and then link the function from mylib. So the functions not prototyped aren't unaccessible.
If void b(void) is not needed by other header file, and you have access to the source file, what about moving the declaration into the source file?
// header1.h
void a(void);
//void b(void);
// header1.c
/* some #include here */
void b(void);
/* other code here */
void b(void) {
/* implement it */
}
Header files only contains functions that should be accessible by user of header. They represent public interface.
Watch this first:
Organizing code into multiple files 1
YouTube link: Organizing code into multiple files 1
Organizing code into multiple files 2
youTube link: Organizing code into multiple files 2
Additionally you can refer Introduction To GCC by Brian Gough to get more insights into compilation and linking process using gcc.
If I'm writing a library that uses a file descriptor for doing stuff, when should I return it from lib_init() for the higher layer code to use and pass to my lib_do_stuff() calls, and when can I leave it as a private "member" in my C library as a static global in .c file?
If I don't think the user of my library should have control or even access to the file descriptor, can I just leave it, much like in C++ it would just be private?
What are the downsides for doing it either way?
Expanding my suggestion with an example.
Your library needs two (at least) header files: One public that the users of your library includes, and one private that you include only in your library source files.
The public could be something like
#pragma once
// This is all that is needed to declare pointers to the internal structure
typedef struct internal_structure STRUCTURE;
// The public API of your library
STRUCTURE *lib_init(void);
void lib_cleanup(STRUCTURE *s);
...
Then you have the private header file
#pragma once
struct internal_structure
{
int fd;
// Other members as needed
...
};
// Possible function prototypes of private functions
Then in your library source files you include both the public and the private header files, and use STRUCTURE for the black-box structure:
#include <stdlib.h>
#include "public.h"
#include "private.h"
STRUCTURE *lib_init(void)
{
STRUCTURE *s = malloc(sizeof *s);
s->fd = open(...);
// Other initialization
...
return s;
}
void lib_cleanup(STRUCTURE *s)
{
// Other cleanup
...
close(s->fd);
free(s);
}
Then the users of your library includes only the public header file, and uses your well-defined API:
#include "public.h"
int main(void)
{
STRUCTURE *s = lib_init();
...
lib_cleanup(s);
return 0;
}
The public functions should all take STRUCTURE * as one of their arguments, typically their first argument, similar to the lib_cleanup function. The function can then use the structure and its members any way they want.
api.h
The following API is assumed to be distributed as a shared library.
#include "apiInternal.h"
internalStruct* API_init();
extern void API_set_member1(internalStruct* apiStruct, int value);
extern void API_set_member2(internalStruct* apiStruct, int value);
apiInternal.h
typedef struct internalStruct {
int member1;
int member2;
} internalStruct;
sample.c
The program sample.c uses api.h and links with the shared library to use the API.
#include "api.h"
int main()
{
internalStruct *myVar = API_init();
API_set_member1(myVar, 5);
API_set_member2(myVar, 6);
}
The dilemma here is,
Should the api.h that the API implementation uses be different than
the api.h distributed to the users of the API? If so, how can I do
this without including apiInternal.h?
Is there a better way to do/design this?
You can build sample.c without including apiInternal.h and the structure definition.
Within api.h drop the #include "apiInternal.h". Instead, declare the structure, this is called a forward declaration, (easiest to drop the typdef) so api.h will look like:
struct internalStruct;
struct internalStruct* API_init();
extern void API_set_member1(struct internalStruct* apiStruct, int value);
extern void API_set_member2(struct internalStruct* apiStruct, int value);
This works because the compiler can build sample.c as it only needs to know the size of the pointer rather than the complete structure declaration. You then only need to include apiInternal.h within your library code. You won't need to distribute apiInternal.h to your users.
If you library code has multiple files, then you will need apiInternalh.h. Each of you library source files will include apiInternal.h. If you library code is a single file, then I typically just define the structure at the top of the library C file, the extra header is not necessary.
This is called an opaque pointer. The Wikipedia article provides an additional example. This is nice way of achieving information-hiding from within C.