C library public header interface - c

I am building a range of C libraries to improve separation of code in a large codebase.
I would like to enforce strict separation using minimal public library interfaces.
The libraries consists of several modules (c + h files), some with internal references.
Currently, the library header files contain both prototypes related to the library interface functions and the public functions that are used internally in the library (in between the library modules).
I would like to somehow filter out the public interfaces which should not be accessible through the library interface (the internal public functions used in between the library modules).
I have come up with the following possible solutions, but I do not feel confident that any of these are optimal:
Maintain two header files for each module. One header file with internal interfaces used within the library and one header file containing the public library interfaces which may be used by the users of the library
Use include guards + a c pre-processor to filter out sections of the header files - with the resulting pre-processed header file only containing the library public functions
Write a custom script to filter the header files based on some syntax using c-style comments e.g. // Lib func \n void function1 ( int test ); For this solution I would be using some standard tool to parse the c header files (such as clang / LibClang).
I expect that this is a standard “problem” building libraries and wonder why it is not possible to find anything on the topic on SOF or google.
Any suggestions to how this can be effectively achieved is highly appreciated.
Thanks

Also, you can use "static const func()" in this case the domain of the function will be the only current .c file. In the fact need an only static function(), but realization static const func() will be better(correct me if I'm wrong in it).

Related

Is there a way to limit the use of a function to its library in C?

So I'm working on a static C library (like a library.a file) for a school project. There are multiple functions, some of which are placed in different files, so I can't use the static keyword. Is there a way that those functions could be limited to the library itself, an equivalent to static for libraries?
So I'm working on a static C library (like a library.a file) for a school project. There are multiple functions, some of which are placed in different files, so I can't use the static keyword. Is there a way that those functions could be limited to the library itself, an equivalent to static for libraries?
The C language does not have any formal sense of a unit of program organization larger than a single translation unit but smaller than a whole program. Libraries are a foreign concept to the language specification, provided by substantially all toolchains, but not part of the language itself. Thus, no, the C language does not define a mechanism other than static to declare that a function identifier can be referenced only by a proper subset of all translation units contributing to a program.
Such limitations are supported by some shared library formats, such as ELF, and it is common for C implementations targeting such shared libraries to provide extensions that enable those facilities to be engaged, but the same generally is not true for static libraries.
Note also that in all these cases, we're talking about the linkage of function identifiers, not about genuinely controlling access to the functions. In principle, any function in the program can be called from anywhere in the program via a function pointer pointing to it.
Frame challenge: why do you care?
The usual accommodation for having functions with external linkage that you don't want library clients to call directly would be to omit those functions from the library's public header files. What does it matter if some intrepid person can analyze the library to discover and possibly call those functions? Your public headers and documentation tell people how the library should be used. If people use it in other ways then that's on them.
It may not be possible to completely "hide" the existence of a set of restricted functions from other source files if they are defined with external linkage, since their identifiers will be visible when linking (as noted in the other answer).
However, if you are only looking to prevent someone from inadvertently calling restricted functions, one of these approaches may be useful:
In some of my projects, I have used #define and #ifdef statements to block restricted functions from being used throughout the program. For example, in my Hardware Abstraction Layer (HAL) library C source files, I typically place #define HAL__ prior to any #include statements. Then I place an #ifdef HAL__ ... #endif block around any restricted function definitions in my header files. Someone with intention could easily easily bypass this by adding #define HAL__ to their source code or by modifying the header file, but it provides some protection against unintentional use of restricted functions and other definitions.
Place the restricted function definitions in a separate header file used to build the library itself (for example library.a) and provide only header files containing non-restricted function declarations with the library. The identifiers for any functions defined will still be visible to the linker, but without the prototypes, it will be difficult for anyone to call them.
Again, if having the identifiers for any restricted functions visible throughout the program would be a problem (for example, duplicating other identifiers), then these options will not work. Also, if the goal is to prevent developers from intentionally calling restricted functions, then these options will not work, although option 2 would make this more difficult. If the intention is only to prevent unintentional calls to the restricted functions and there is no concern with having duplicate identifiers in the program, then these options may help.

Are C libraries distributed with textual header files along with the binary files?

I'm learning about static and dynamic libraries in C and how to make them.
One thing that keeps bothering me is this:
Suppose a file is using the library mylibrary by doing #include <mylibrary.h>.
Does this mean that C libraries are distributed along with matching textual header files? Or is mylibrary.h somehow magically exported from the binary library file?
Does this vary between different approaches, or whether the library is static or dynamic?
Yes, and depending on the platform, you get even more files to distribute with it. It's a quite messy story. At least, it doesn't matter whether the library is static or dynamic (aside from linker parameters).
The header file is necessary because the compiled binary does not contain enough information to be usable by the compiler. With some platform-based variance, a C binary typically only has enough metadata to identify functions and global variables by their name. That metadata does not include the types (or count) of parameters, return types, structure or union definitions, the type or size of global variables, etc. All of this information typically is encoded in the headers that are distributed with the library. (Conveniently, it also means that anything that does not exist in the header is hidden from the developer; this is what allows you to create non-public functions in a library, that users shouldn't call directly.)
On some platforms, binaries don't even contain function names. Instead, functions are referenced by their position in an "ordinal table". On those platforms, the library has to ship a header, the executable binary, and an additional file that translates from the name of the function in the header to the index of the function in the ordinal table, such that "void hello(void)" might be "function at index 3 in ordinal table" to the linker.
Conversely, including a header does not (usually) link against the library that it accompanies. This is possible on some platform, like Windows, on which there are special compiler directives that you can put in a header and that tells the linker to link against some library, but it is not standard behavior and you can't expect it to be a reality on any other platform.
Up and coming are modules, which provide a better user experience to link against binaries. A module is yet another file that you can package with your binary and that says "here are all my headers and here are all my libraries". Using modules, it's possible to write something like "import MyLibrary;" and it'll get you all the headers and all the linker arguments that you need. I believe that there are no C-standard modules yet; C++ is getting there with C++20.

Using my linked list code in a new c program

Apologies in advance since this seems extremely basic.
I have my linked list file, linkedList.c, and I would like to include it in my new c file so that I don't have to code the whole linked list in again. In Java I just had to place it in the same folder and then I could create an object of the class linkedList in the new file however C doesn't seem to work this way. If I try to use
#include "linkedLIst.c"
at the start of my new file then I receive errors since main has now been defined twice along with my Boolean variable. How exactly do I go about solving this?
You could #include any kind of (syntactically valid) C code, but you generally should not (by convention) include a .c file. Read more about the C preprocessor.
In practice, you should consider making some library (to be linked for reuse), and separate your shared code into a .h header file (containing definitions) that you would #include for re-using and an implementation .c file. Of course don't define any main in the shared source code. In some simple cases and on some operating systems, you might also share a single (or some few) object file (and related header files).
Your shared header would declare functions and extern variables (and #define some macros). It could also contain the definition (with their body) of short static inline functions.
Your shared implementation would define these (and others) functions and variables.
C programming entails a lot of conventions (and you need to define your own ones). Look at existing examples (some free software source code from github, or from a Linux distribution). For reusable container libraries, look into glib (from GTK) and also sglib (which uses a lot of preprocessor tricks) and many others.
Because C does not have any notion of namespaces it is wise (for readability and other reasons) to have a consistent naming convention, e.g. starting all the public names (of functions and variables and macros in headers) of your library by some common prefix.
You need to define a header file, linkedList.h, and declare your linked list function prototypes in there, which you probably already have defined in you linkedList.c file. And then, you can use '#include linkedList.h' to reuse your code.

static library doesn't contain macro

I have a static library project (written in C language) and another sample project (written in C language) under Visual Studio 2015. I can use the functions located at the library in the sample project without any problem. My problem is that I have a macro in one of the header files in the static library project and I can't see (or use) this macro in the sample project. I receive this error: "unresolved external symbol ADD1 referenced in function main". How can I use this macro in the sample project?
Note: I use the library file in the sample project thanks to this pragma this pragma: #pragma comment(lib, "mylib.lib")
I do not want to include any of the header files of the static library project. They are not supposed to be seen by other projects.
I think there is some confusion.
To make use of any library, you must know about its functions, datatypes (e.g: enum, struct, typedef), macros, etc... This all comes together to form the library's 'API'.
Most libraries (not all) will have some internal headers. You are correct, these are not supposed to be seen by other projects, and will be used strictly internally.
All libraries will have some 'public' headers that define their API. A code base Without a public API is either useless, or actually an application that stands on its own.
Include your header with the #include directive, not with some pragma.
A header should be written so that it is the public interface to your library, even if the library code itself may not be open. Either the macro is public and can then be declared in the header, or it is not public in which case you should encapsulate it inside the library.
If the library code is pre-compiled and delivered as a binary, either declare it in a C file or in a H file that the caller does not have access to.

Hiding implementation and helper functions in C header file

Since the files i include are simply copied into the file I include from, I can call any function that the header file implements.
static declarations won't help either as far as I understand.
How can I publish some header file and prevent the user's main C file from calling some functions in my header?
(Of course not really hide because he can just look at the source, but help him not to use functions that are not intended to be called directly)
Don't really hide them (BTW, making your library free software is usually worthwhile. You could use the LGPL license....). But put these internal functions in a separate header, e.g. foo-internals.h which is #included from the public foo.h and comment these functions as internal only!
Also, define some naming conventions, e.g. use some general foo_ prefix for public functions, and foointernal_ for "private" functions. Use once-only headers when needed.
You could use visibility pragmas and function attributes (set the visibility to hidden), at least on Linux or with GCC.
An API is not only defined by header files, but also by convention and by documentation. An undocumented function, or a function commented to be internal, should not be expected to be part of the API.
Take your inspiration by studying source code of real existing free software libraries (e.g. GTK, Posix libc such as MUSL libc or GNU libc, etc....).

Resources