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.
Related
I'm in the process of writing a library that provides a sha256 implementation. The library will be given to vendors that may want to provide their own sha256 functions that are optimized for their platform. So, the API of this library allows the client to pass in function pointers to their sha256 code.
int mylib_set_sha256_impl( /* function pointers */ );
Henceforth, all algorithms will use the function pointers provided internally instead of the stock sha256 code provided by the library.
The question is: how can I facilitate dead code removal during link time, such that the default sha256 implementation in this library is removed??
This is an API design question as much as it is a compiler-optimization question.
There are no special requirement as far as linker is concerned, and no weak aliasing need be considered.
The basic rule is: As long as the user code doesn't reference any symbols in a given .c or .s file that you linked into your library, the said file's contents won't end up in the executable.
In the scenario you describe, your functions may never become dead code since your "live" code perhaps references their addresses to set up default function pointer values. To make sure that doesn't happen, you have to do the following:
Refer to the replaceable functions only from within a user-callable optional default_init function.
The default_init must never be called anywhere in your code, neither must any of the functions be referenced anywhere but within default_init.
Have the replaceable functions, and the init function, put into at least one .c or assembly file that is not used for any of the other code.
For your user to replace all the functions, they simply have to never call the default_init function. If you wish functions to be replaceable one-by-one, you have to, additionally:
Have each replaceable function in its own .c file.
Have the user not call the default_init directly, but pass the desired default or user-provided implementations to your init function.
What you're doing, in effect, isn't "overwriting" any implementation, but simply not using it at all.
Example (include guards omitted for clarity):
// api.h
void api_fun1(void);
void api_fun2(void);
void api_default_init(void);
void api_user_init(void (*f1)(void), void (*f2)(void));
void api_use_funs(void);
// api_internal.h
extern void (*api_f1)(void);
extern void (*api_f2)(void);
// common.c
#include "api.h"
#include "api_internal.h"
void (*api_f1)(void);
void (*api_f2)(void);
void api_user_init(void (*f1)(void), void (*f2)(void)) {
api_f1 = f1;
api_f2 = f2;
}
void api_use_funs(void) {
api_f1();
api_f2();
}
// api_fun1.c
#include "api.h"
void api_fun1(void) {}
// api_fun2.c
#include "api.h"
void api_fun2(void) {}
// api_default_init.c
#include "api.h"
#include "api_internal.h"
void api_default_init(void) {
api_f1 = api_fun1;
api_f2 = api_fun2;
}
Let's say that the user wants to override api_fun2 with their own:
// main.c
#include "api.h"
#include <stdio.h>
void my_fun2() {
printf("%s\n", __FUNCTION__);
}
int main() {
api_user_init(api_fun1, my_fun2);
api_use_funs();
}
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
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.
In C++ I can have a getter function declared inline in a header file:
class Cpp_Example
{
public:
unsigned int get_value(void)
{ return value;}
private:
unsigned int value;
};
By including this header file, client methods and functions can use the getter function to access a private variable.
I'm looking to model this concept in the C language:
hello.h:
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
inline void Print_Hello(void)
{
extern const char hello_text[32];
puts(hello_text);
}
inline void Print_Value(void)
{
extern unsigned int value;
printf("Value is: %d\n", value);
}
#endif // HELLO_H
hello.c:
const char hello_text[32] = "Hello World!\n";
static unsigned int value = 5U;
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "hello.h"
int main(void)
{
Print_Hello();
Print_Value();
// puts(hello_text);
return EXIT_SUCCESS;
}
I get a linker error from gcc:
$ gcc -o main.exe main.c hello.c
/tmp/cc41ZB8H.o:main.c:(.rdata$.refptr.value[.refptr.value]+0x0): undefined reference to `value'
collect2: error: ld returned 1 exit status
Is there a way to have an inline function (in a header file) access a static variable in another translation unit?
Or is there a way to implement an inlined getter function?
I'm using IAR Embedded Workbench, ARM7TDMI processor on an embedded platform.
The gcc compiler is used to testing concepts on the PC.
Edit 1: Background
I'm looking to optimize getter calls that are inside a critical section. The objective is to reduce the time spent in the critical section.
Edit 2: No Globals
The Coding Guidelines our shop uses states no global variables.
Also, this system is an RTOS running MicroCOSII.
First of all, the same way you have private variables in C++, you probably mean to have private variables for a struct rather than global. With that assumption, here's one model you can use:
/* some_type.h */
struct some_type
{
int public_data;
void *privates;
};
struct some_type_privates
{
char hello[32];
int value;
};
inline const char *get_hello(struct some_type *t)
{
struct some_type_privates *p = t->privates;
return p->hello;
}
inline int get_value(struct some_type *t)
{
struct some_type_privates *p = t->privates;
return p->value;
}
/* similarly for setters */
The same way that your private variables and their getters and setters are in the header file, you can do it in C, too.
On the side, I'd like to recommend not to try coding C++ in C. While C++ likes to complicate things a lot to prevent the idiot from breaking something, C on the other hand trusts the programmer has some degree of intelligence. Whether these assumptions are justified are not the matter of discussion. But what I mean to say is that the spirit of C is not to hide a variable so that the programmer doesn't mistakenly access it.
That said, this is how you would normally make a struct in C:
struct some_type
{
int public_data;
char hello[32]; /* read only */
/* internal */
int value;
};
(with enough documentation of course) which tells any programmer that she shouldn't write over hello but can freely read it (what you were trying to achieve by an inline getter). It also tells that value is private so the programmer shouldn't read or write it.
You can see this in many POSIX functions that take or return a struct. Some that don't need to control the access let you freely modify the struct, such as stat. Some that do need to check the input have setters, such as pthread_attr_*.
You need to remove the static keyword. static definitions are local to the compilation unit.
As Shabbas wrote, it doesn't really work that way in C.
The keyword inline implies static, even if the compilers doesn't actually inline it. If it is such a short function, it will probably inline it. But the point is, if it would not be static, it could not even consider inlineing it, as the function would need to be visible externally, it would need an address, which an inlined function doesn't have.
Since it is local in your compilation unit, it can only work on stuff known inside that compilation unit. Thus you need to say something about that value variable, much like you do need to mention it in the C++ header as well, only in C there is no such thing as private .
You can not have Inlineing and data hiding in the same case, neither in C, nor in C++.
Assuming you mean for global, statically-allocated variables you can do this:
In Example.h:
#ifndef Example
#define Example
extern int getValue();
#endif
In Example.c
#include "Example.h"
static int value;
inline int getValue() {
return value;
}
// All the functions in Example.c have read/write access
In UsesValueExample.c
#include "Example.h"
// All the functions in UsesValueExample.c have read-only access
void printValue() {
printf("value = %d", getValue());
}
If you want to get fancy and force all code to access through a getter and setter, e.g. if the variable is volatile and you want to heavily encourage all the methods to use a local cache of the variable to avoid the overhead of accessing the volatile, then:
In VolatileExample.h:
#ifndef VolatileExample
#define VolatileExample
extern int getValue();
#endif
In VolatileExample.c
#include "VolatileExample.h"
void setValue(); // Forward declaration to give write access
// All the functions in VolatileExample.c have read/write access via getters and setters
void addToValuesAndIncrementValue(int const values[], int const numValues) {
int value = getValue(); // Cache a local copy for fast access
// Do stuff with value
for (int i = 0; i < numValues; i++) {
values[i] += value;
}
value++;
// Write the cache out if it has changed
setValue(value);
}
// Put the definitions after the other functions so that direct access is denied
static volatile int value;
inline int getValue() {
return value;
}
inline void setValue(int const newValue) {
value = newValue;
}
In UsesVolatileValueExample.c
#include "VolatileExample.h"
// All the functions in UsesVolatileValueExample.c have read-only access
void printValue() {
printf("value = %d", getValue());
}
Here is a pattern I've been using to hide global variables.
Inside some header file, such as module_prefix.h, you declare the following:
typedef int value_t; // Type of the variable
static inline value_t get_name(void) __attribute__((always_inline));
static inline void set_name(value_t) __attribute__((always_inline));
static inline value_t get_name(void) {
extern value_t module_prefix_name;
return module_prefix_name;
}
static inline void set_name(value_t new_value) {
extern value_t module_prefix_name;
module_prefix_name = new_value;
}
/* Note that module_prefix_name is *no longer* in scope here. */
Then of course you have to define module_prefix_name in some compilation unit, without the static keyword, as discussed above, e.g. in module_prefix.c you have the following:
#include "module_prefix.h"
value_t module_prefix_name = MODULE_PREFIX_NAME_INIT_VALUE;
This is essentially the same pattern that Thomas Matthews tried to use, drilling down to the essence and making sure that the compiler inlines the functions always and does not unnecessarily generate explicit function bodies. Note the use of module_prefix as poor man's name spaces.
I have a header file port.h, port.c, and my main.c
I get the following error: 'ports' uses undefined struct 'port_t'
I thought as I have declared the struct in my .h file and having the actual structure in the .c file was ok.
I need to have the forward declaration as I want to hide some data in my port.c file.
In my port.h I have the following:
/* port.h */
struct port_t;
port.c:
/* port.c */
#include "port.h"
struct port_t
{
unsigned int port_id;
char name;
};
main.c:
/* main.c */
#include <stdio.h>
#include "port.h"
int main(void)
{
struct port_t ports;
return 0;
}
Many thanks for any suggestions,
Unfortunately, the compiler needs to know the size of port_t (in bytes) while compiling main.c, so you need the full type definition in the header file.
If you want to hide the internal data of the port_t structure you can use a technique like how the standard library handles FILE objects. Client code only deals with FILE* items, so they do not need (indeed, then generally can't) have any knowlege of what is actually in the FILE structure. The drawback to this method is that the client code can't simply declare a variable to be of that type - they can only have pointers to it, so the object needs to be created and destroyed using some API, and all uses of the object have to be through some API.
The advantage to this is that you have a nice clean interface to how port_t objects must be used, and lets you keep private things private (non-private things need getter/setter functions for the client to access them).
Just like how FILE I/O is handled in the C library.
A common solution that I use:
/* port.h */
typedef struct port_t *port_p;
/* port.c */
#include "port.h"
struct port_t
{
unsigned int port_id;
char name;
};
You use the port_p in function interfaces.
You will need to create special malloc (and free) wrappers in port.h as well:
port_p portAlloc(/*perhaps some initialisation args */);
portFree(port_p);
I would recommend a different way:
/* port.h */
#ifndef _PORT_H
#define _PORT_H
typedef struct /* Define the struct in the header */
{
unsigned int port_id;
char name;
}port_t;
void store_port_t(port_t);/*Prototype*/
#endif
/* port.c */
#include "port.h"
static port_t my_hidden_port; /* Here you can hide whatever you want */
void store_port_t(port_t hide_this)
{
my_hidden_port = hide_this;
}
/* main.c */
#include <stdio.h>
#include "port.h"
int main(void)
{
struct port_t ports;
/* Hide the data with next function*/
store_port_t(ports);
return 0;
}
It is generally no good to define variables in a header file.