How to hide internal dependencies in C? - c

My goal is to write a library which exposes only a public API in C language.
Let's say I'm writing a library, and it depends on two other libraries: a.c, and b.c
Contents of a.c:
int a(void) { return 1; }
Contents of b.c:
int b(void) { return 2; }
And let's say my library is m.c and its contents are:
#include "a.h"
#include "b.h"
int m(void) {
return a() + b();
}
My goal is to hide int a(void) and int b(void) so that they don't pollute the global namespace. I want the only symbol to be exported to be int m(void). That is, if my user defines their own a, they shouldn't get a link error:
#include "m.h"
int a(void) { // SOME OTHER FUNCTION
return 5;
}
int main(void) {
return m() + a();
// THIS WOULD CREATE A LINK ERROR,
// SINCE THERE ARE TWO `A` FUNCTIONS
// IN SYMBOL TABLE
}
The only thing that comes to mind is to define macros with the same name as a and b like this:
#define a internal_a
#define b internal_b
This would create name-mangled symbols, and once user has an executable, they can strip away internal dependency symbols using strip -s file.elf
Another way would be to design internal dependencies as UNIX style filter programs. However, this would require serialization, and would only work if all the internal dependencies belong to me.
Both methods are not ideal, so I'd like to see if there are any better ways to achieve this in C. I'm also not sure how C++ solves this. Most probably the symbols C++ exposes have names namespace-funcname-params.
edit: This would be trivial if I had all my dependencies in a single file. I'd simply use static keyword where needed. My question is specifically about multiple file libraries.
edit: Even though standard C doesn't provide a portable solution for this, the problem is still very common in programming. So, solutions might not be directly relevant with C, but more with the build tools (compiler, linker, preprocessor..)

Related

Should every function in C have its own .c file ? or can i put all the functions of my program in one .c file?

I'm new to C programming and I just started studying functions.
Should I put each function in a .c and .h file, or can I put all of the functions and headers in one .c and .h file?
Determining where to put different parts of your code is something that comes with both your personal and the programming language experience. Considering your mention that you're currently learning about functions, let me go over a couple main factors in deciding where to put your functions.
Prototypes
When writing your code, before you can use a variable, you need to declare it first. The same goes for functions. The first, simple approach is defining a function before you use it.
int add(int a, int b) {
return a + b;
}
int main(void) {
int result = add(10, 8);
return 0;
}
Here I defined a function add() and called in the function main(). This piece of code will simply compile and run. However, what if I placed my definition of the add() function below the main() function?
int main(void) {
int result = add(10, 8);
return 0;
}
int add(int a, int b) {
return a + b;
}
This piece of code will result into a compilation error. The compiler doesn't know which add() function I'm calling in the main() function, because no add() function has been defined yet. Sometimes you can solve this problem by simply re-arranging the code. Other times that is not possible and that's why prototyping comes into play.
int add(int a, int b);
int main(void) {
int result = add(10, 8);
return 0;
}
int add(int a, int b) {
return a + b;
}
This tells the compiler there is a function add() accepting two int parameters, that will be defined later in the code. The compiler is satisfied and indeed - this piece of code compiles without an issue once again.
The #include directive
Including headers in C is a bit troublesome. It is the method of including the definitions in header files inside your .c files, and it's done in the simplest way imaginable - every #include <my_header.h> directive in your C code gets simply replaced with all contents of the my_header.h file before the compilation. For example imagine the following files:
my_header.h
// Hello, I am the my_header.h file
// I currently have no definitions
my_program.c
#include "my_header.h"
int main(void) {
// Do nothing
return 0;
}
If I compile just my_program.c, the preprocessor will examine the file before the compiler does. It will find an #include directive, look for a file named my_header.h, find it and copy its contents into the .c file simply like this:
// Hello, I am the my_header.h file
// I currently have no definitions
int main(void) {
// Do nothing
return 0;
}
Then the resulting file will be given to the compiler.
While this approach is incredibly simple and easy to implement, it makes C very prone to errors and hard to maintain, unless great care is taken. This is for example the reason include guards exist. Imagine you include two files in your main file. Now both of those two files include one, third file. After all the replacements done, you'll end up having the third file pasted twice inside your code, which will result in naming conflicts during a compilation.
This also means you technically can put any sort of code inside the header files. However, in my whole career, I was met with only one case when such code was acceptable (in a bare metal embedded system program), so I can't stress this out enough - unless you really, really know what you're doing, never put anything other than function prototypes, variable declarations, includes and macros inside a header file. Doing otherwise is the easiest way to have your code break in the most inexplicable of ways.
The conclusion
The style I've seen the most often (and also personally follow) is separating sets of functions with similar functionalities into individual .c files. This .c file contains nothing, but function definitions (i.e. the code) and a single #include directive of the header file this .c file is associated with. This keeps all the functions in a separate translation unit.
The header file with include guards (isn't needed when you don't include the file more than once anywhere, but it's a good habit to get used to) contains all the required #include directives of system libraries, other header files in your project and function prototypes of every function in the respective .c file. Whenever you then need to use those functions elsewhere, include this header file in any other header file. System libraries are generally included using <> while your own files are included using "".
As remarked by other answers, the .c file containing the main function often exists without its respective header file. All other .c files should have a header file associated. This is mostly in line with the Google's C++ Style Guide.
An example
For any smaller project, you most likely won't need more than just two files. Take these as an example:
main.h
#ifndef _MAIN_H_
#define _MAIN_H_
#include <stdio.h>
// any other includes
int add(int a, int b);
int sub(int a, int b);
int main(int argc, char *argv[]);
#endif // _MAIN_H_
main.c
#include "main.h"
int main(int argc, char *argv[])
{
int first = 10;
int second = 8;
int third, fourth;
third = add(first, second);
fourth = sub(third, first);
return 0;
}
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
If you were to add more mathematical functions, say mul() and div(), it'd be appropriate to take them all out of the main.c file and create a new pair of files - something along the way of my_math.c and my_math.h, following the same rules as the rest of your project. Then, to call the mul() function in your main function, you'd need to #include my_math.h inside main.h.
A lot of this comes with the experience. Feel free to explore other styles and try out what works the best for you. The most important part in all of this is staying consistent. Pick a style and stick to it. Best of luck in your studies!
Should every function (definition) in C have its own .c file?
No. should not, but can. It's a matter of coding-style, but it's not the preferred way to do so and unusual. It increases compilation and linking time.
Or can I put all the function (definitions) of my program in one .c file?
Yes, you can. Also again, matter of one's own coding-style.
If you got a lot or several functions in your code, you can also group the function definitions into own .c files and then link the files when invoking the compiler.
This way you keep clarity.
One way is also to keep all function definitions in a separate .c file, apart from main.c, which contains the main function.
Should I put each function in a .c and .h file?
Function definitions can't be placed inside of .h files.
.h consist only of function and other variable declarations, as well as macro definitions.
Function definitions need to be placed in .c files.
If you mean to place each function definition into an own .c file and each function declaration in an own .h, that definitely does not need to be either.
It even would confuse you all the way up.
You actually can do so, but it is definitely not recommended.
Or can I put all of the functions and headers in one .c and .h file ?
Again here you can't put function definitions in an .h file.
But you can pack all function definitions in one .c file and all function declarations in one .h file.
No! There is no need to do it at all. That would be affect your performance really badly.
Usually we only tend to create new files .h to store functions/methods that we want to use repeatedly in other projects or programs I guess.
Your program should be as follows:
Let's call this prog1.c
#include <only libs that you need>
void functionA (parameterType parameter){
//Whatever your function needs to do
}
int main(){
//this is your main function and where the program will start working.
functionA(parameters) /*Here is how you call functionA if it's void giving it's needed parameters.*/
}
Later on, with more knowledge you'll learn when you need to store or not the functions in others files to learn and keep it organized. There's no need for that now. You should focus the most on learning how they work and communicate with each other.
If you need to use functionA in other file, well then you will just need to include that .c file, like this:
In prog2.c you start it by calling out
#include "prog1.c"

How to control exported symbols when writing a static library in Visual Studio?

I want to build a static library, which has some functions/variables/etc. exported, and others internally used by the library. Everything exported is C-style.
How to achieve this?
What I have tried is the following:
MyLib.h
int Test(int a, int b);
MyLib.cpp
#include "MyLib.h"
int Private(int a, int b)
{
return a * b;
}
int Test(int a, int b)
{
return Private(a, b);
}
And this is how I use the library:
Main.cpp
#include "MyLib.h"
int main()
{
int x = Test(4, 6);
...
}
All these seem to work well.
However, I find that the function Private is also exported.
Thus the following code will also compile and link:
Main.cpp
#include "MyLib.h"
int Private(int a, int b);
int main()
{
int x = Private(4, 6);
...
}
Therefore, I guess that I have polluted the global namespace, and now I cannot define a function called Private in Main.cpp, because the linker will complain that this symbol already exists.
So how do I control which functions/variables/symbols are visible to the codes that use the library?
After doing some search, I find that declaring the Private function in MyLib.cpp as static seems to solve the problem. However, I'm not sure if this is the best way. To me, it would make more sense to "mark" those that I want to export, rather than to "mark" those that I want to hide, since I only want to export a small portion of all the symbols.
Simplified version:
The OS doesn't recognize static libs as being anything it understands. It only deals with exe's, dll's, and data files. You build a static lib to merge it into 1 or more exe's and|or dll's, basically to save recompiling it for each.
As such, the expectation is that you want to be able to access all the code|data in the static lib when building the exe or dll you've linked it to.
In contrast, an exe|dll can have security applied by the OS, and is considered a 'final product', so by default everything is private unless explicitly marked as exported.
So, either:
use a static lib and put all 'private stuff' in a .cpp e.g. marked as static like you've discovered, or in an anonymous namespace, or ...
use a dll and mark all 'public stuff' as exported.

C - Include only specific function

Alongside main.c file, I have following my_custom_data_structure.c file in my project. My my_custom_data_structure.c file contains a lot of variables, functions, etc.
I am using #include "my_custom_data_structure.c" directive in main.c.
Problem
I would like to import only single function called foo from my_custom_data_structure.c. I don't need all the variables and functions, which are declared in my_custom_data_structure.c file.
Any insights appreciated.
File structure
-
|- main.c
|- my_custom_data_structure.c
Content of my_custom_data_structure.c
#include <stdio.h>
int DELAY = 20;
int SPEED = 7;
char GRANULARITY_CHAR = 'g';
unsigned int RANGE = 3;
void foo(){
// TODO: In future, this function will print SPEED.
printf("foo works!");
}
/*
The rest of this file is filled by a lot
of code, which is not needed for main.c
*/
Content of main.c
#include <stdio.h>
#include "my_custom_data_structure.c"
int DELAY = 3;
int main(){
foo();
printf("Delay is %d", DELAY);
return 0;
}
UPDATED: Added working example
The usual way is to compile them separately. So you have your main.c, and your extra.c, and you should create a extra.h (and include it in main.c).
In this extra.h, put in declarations for anything that is to be exported from your extra.c file.
For example any functions that should be available to other files. All other functions should be declared/defined only in your extra.c as static, so that they are not available as symbols to be linked when main.c is compiled.
Normally, you don't include source files (.c) inside other source files (or inside headers). It's possible (and occasionally necessary), but it isn't usual.
Unless you've designed the my_custom_data_structure.c to allow you to specify which functions are to be compiled, you get everything in the file. For example, you could use:
#ifdef USE_FUNCTION1
void function1(void *, …)
{
…
}
#endif /* USE_FUNCTION1 */
around each function, and then arrange to
#define USE_FUNCTION1
before including the source, but that's not usually a good way of working. It's fiddly. You have to know which functions you use, and which other functions those need, and so on, and it is vulnerable to changes making the lists of USE_FUNCTIONn defines inaccurate. Of course, the source code might have blocks of code like:
#ifdef USE_FUNCTION1
#define USE_FUNCTION37
#define USE_FUNCTION92
#define USE_FUNCTION102
#endif /* USE_FUNCTION1 */
so that if you say you use function1(), it automatically compiles the other functions that are required, but maintaining those lists of definitions is fiddly too, even when the definitions are USE_MEANINGFUL_NAME instead of a number.
Create a header (my_customer_data_structure.h) declaring the functions and any types needed, and split the implementation into many files (mcds_part1.c, mcds_part2.c, …).
Compile the separate implementation files into a library (e.g. libmcds.a), and then link your program with the library. If it's a static library, only those functions that are used, directly or indirectly, will be included in the executable.

Functions declared and defined in a .c file

As I was going through a huge source code, I came across some files where there is only one function declared in, let's say, "code.h" but in "code.c" there are many functions declared and defined.
What is the exact use of declaring and defining functions in .c files ?
How can we access one of those functions in a source file from other source file ?
It would be helpful if anyone can provide an example. Thanks
Splitting a complex routine in multiple smaller routines might make the code easier to understand and also would allow you to follow the single responsibility principle (What is an example of the Single Responsibility Principle?). By declaring and defining them only in a .c file (and declaring them static), you can hide the internal details from users.
If you, for instance, create a library, then your header could only show the public functions you'd like your users to use.
So only put your functions in a header if you'd like those functions available to anyone who includes the header.
If you'd like to keep a function internal to your .c file, seriously consider adding the static keyword as well: what is the advantage of static function?
---edit---
How can we access one of those functions in a source file from other source file ?
If the function isn't static, you could technically declare it anywhere* you'd like and use it there as well. Though, by the above argument, this would be bad practice.
Example:
a.c
int secret_a(int x)
{
return x+1;
}
main.c
#include <stdio.h>
//access a secret function from a.c
int secret_a(int);
int main()
{
printf("secret_a(3) gives: %d\n", secret_a(3));
return 0;
}
(*) anywhere allowed by the C language
How can we access one of those functions in a source file from other source file ?
That is the whole idea with defining some functions in the header, and some only in the c-file.
The functions defined in the header, can be called by other source files.
The functions only defined in the source file, can be hidden - it is a usual practice to mark functions, only declared in a source file, as static.
That makes their visibility limited to the file-scope (only code inside the same file can 'see' the functions).
The reason why this is done is to split the code into a more cleaner and sorted format so that functions concerning a particular operation can be grouped together in to one file and then called from other file. NOTE: this is not mandatory to do but a good programming practice.
Now there are two ways to do it :
1. including the files
2. Declaring the function as extern and then linking them at linking time.
1.
Including the file is the method that you are probably seeing in your code at hand. Functions are defined in one file and that file is included using #include"filename.[h/c]" and then calling the function as it were declared in the given file.
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
#include"file_to_include.c"
int main()
{
my_func();
return 0;
}
to compile you just do
gcc file_that_include.c
using extern you can do the same but with out using the #include directive
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
extern void my_func();
int main()
{
my_func();
return 0;
}
In this case while compiling you need to provide both files to the compiler
gcc file_that_include.c file_to_include.c
I would suggest reading up on the "extern" keyword.
From what I can understand in your question you have two files - "code.h" and "code.c". However, "code.h" only declares certain functions in "code.c":
code.h
int func1();
int func2();
code.c
int func1()
{
return 1;
}
int func2()
{
return 2;
}
int func3()
{
return 3;
}
main.c
#include "stdio.h"
#include "code.h"
extern int func3();
int main()
{
printf("%d ", func1());
printf("%d ", func2());
printf("%d ", func3());
}
Compiling using gcc:
gcc main.c code.c
yields:
main.c: In function ‘main’:
main.c:10:17: warning: implicit declaration of function ‘func3’ [-Wimplicit-function-declaration]
printf("%d ", func3());
and when executed:
1 2 3
The "extern" keyword basically tells the compiler "there is a definition for a function with this declaration" for compiling. During linking the linker will find the definition, and link to it.
This is however a clumsy way of doing it, since the caller ("main.c") needs to know what is going on in "code.c", and continually add more extern declaration, etc. etc.
So rather include functions you which to have global scope in "code.h". If there are functions in "code.c" which od not have global scope, consider making them "static".
Some more reading:
Effects of the extern keyword on C functions

Header Files in C

I have been reading about C for a while now and decided lets write a little add program, nothing fancy at all. My understanding of C headers is that they are "interfaces" (such as like java and other languages) but where you can also define variable that either have set values or not..
So I wrote this:
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
int main(int argc, char** argv) {
printf("hello World\n");
add(12, 18);
return (EXIT_SUCCESS);
}
int add(int a, int b){
int value = a+b;
printf("value = %d\n", value);
return 0;
}
It has a header file that looks like such:
#ifndef SAMPLE_H_GUARD
#define SAMPLE_H_GUARD
int add(int a, int b);
#endif
I thought header files, and this is where I am lost on their definition, was suppose to define the use of add, so all I would have to do is call add - From my understanding, I define the rules of add and then implement the functionality of add....
Also, A lot of the material I have read shows one header file for multiple C files. where as a lot of projects today have one header per one c, meaning Sample.h belongs to Sample.c and nothing else.
Can some one shed some light on this?
Could I have done this like so:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
int main(int argc, char** argv) {
printf("hello World\n");
add(12, 18);
return (EXIT_SUCCESS);
}
add.c
#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
int add(int a, int b){
int value = a+b;
printf("value = %d\n", value);
return 0;
}
sample.h
#ifndef SAMPLE_H_GUARD
#define SAMPLE_H_GUARD
int add(int a, int b);
#endif
I believe in the book I was reading: C Programming Language they had a calculator example split up like this, my question is how does C know where add is defined? It knows the rules for it based on the header file, i think, but not where the actual implementation is ....
There example where they split of the files like such doe not have something like #include "add.c" all they do is include the header file in the files that either implement or use this functionality.
Note: obviously the calculator example and my example are going to be different but fundamentally the same - for those who have the book. I am just lost on how to use header files effectively and efficiently.
A header file in C would declare the function add for those modules that need it, but not define the function. The function is still to be defined in its own module (e.g., in your case, add.c).
So in general, to make a function foo available to several modules, you would normally:
Choose a header file (maybe it's own if there are other associated
defines, etc) to declare foo. For example, perhaps foo.h would
have void foo(...);
In some module, perhaps foo.c, you would define the complete
function foo.
In any module that wants to call foo, you would #include "foo.h"
(or whatever header you used) and call the function.
When you compile/link the code, you would make sure all modules,
including foo.o or whatever module has foo defined in it, were
present.
A declaration, given in the header file, provides (of course) the function name, the function return type as well as listing all the parameters and their types. This is all the compiler needs to know to figure out how to call the function from the calling module. At link time, addresses are all resolved so that the modules then know exactly where the function is in its own particular module.
My understanding of C headers is that they are "interfaces" (such as
like java and other languages) but where you can also define variable
that either have set values or not..
This is not correct. You cannot "define" variables - well, you can but that will cause multiple definitions error while compiling code if you include header more than once.
Could I have done this like so:
Regarding your code - both variants are correct. C language uses headers to read declarations and hence headers are optional as well. You can have your code split into as many as you want .h and .c files. Compiler will create an object file for each .c file. All .h files included in a c file are basically embedded in that C file "before compilation" i.e. in preprocessing phase. Linker then comes in picture which combines objects to produce the executable.
Please don't hesitate if something is not clear in my answer.

Resources