Default function implementation for linking - c

I have a family of executables pieced together from a set of .o files. There's some reusable ones, and then usually a couple of executable specific modules. One of the reusable pieces wants to provide a sort of "application hook". But many of the executables just do a standard no-op thing. While a couple of others actually want to define interesting behavior for said hook.
What would be ideal, is if there was a way to provide a standard default version of the function, which the linker would use if none of the other .o files defined said function, but if they did, use the others.
Is there any way/technique to approximate this sort of thing with just straight C?

If you're using GCC as your compiler, then you can declare the replaceable functions like this:
void foo() __attribute__ ((weak));
Here's an example on how this works. In your main.c file:
#include <stdio.h>
void foo()__attribute__ ((weak))
{
printf("%s", "Hidden foo\n");
}
int main()
{
foo();
return 0;
}
In another file, foo.c:
#include <stdio.h>
void foo()
{
printf("%s", "foo\n");
}
Now when you only compile, link and run main.c, you'll get:
gcc main.c -o main
./main
Hidden foo
If you instead also compile foo.c, you'll get:
gcc main.c foo.c -o main
./main
foo
The weak version of foo() was replaced.
On a real setup, you would probably use a header file to provide the function prototypes:
void foo();
and then implement the weak version of those functions like this:
__attribute__ ((weak)) void foo()
{
// ...
}
You could also use a macro to make this a bit more readable:
#define WEAK_SYMBOL __attribute__ ((weak))
So that you'll get:
WEAK_SYMBOL void foo() { /* ... */ }

Related

multiple definitions of main --> how to add only some functions from another header?

In C I get the linker error multiple definition of `main'. Yes, that is true but:
Why does the linker try to include the second (ext.c) main function although I have just included the header ext.h? I'd expect, the linker only links the functions whose prototypes have been found or which are needed by the initial main?
How can I solve this that
a) test compiles and gets linked without issues (just use the func() from ext.c) and
b) also ext.c can be compiled and linked as separate application?
The (example) code:
//file: test.c
#include "/home/stefanm/test/test.h"
void main (int argc, char * argv[])
{
uint8_t var = 123;
printf ("main(): var= %i\n", var);
func (var);
}
//file: test.h
#ifndef TEST_H
#define TEST_H
#include <the rest>
#include "/home/stefanm/test/ext.h"
#endif
...and the external module:
//file: ext.c
#include "/home/stefanm/test/ext.h"
uint8_t func (uint8_t i){
printf ("func(): Variable i is %i", i);
return 0;
}
void main () {
printf ("ext main func");
}
//file: ext.h
#ifndef EXT_H
#define EXT_H
#include "all needed headers"
uint8_t func (uint8_t);
#endif
I call the compiler with gcc test.c ext.c -o test
Your external module should not have main() because it's a module and not an application. You should just move main() from your module to a separate file:
//file: app.c
#include "/home/stefanm/test/ext.h" // <-- BTW, using absolute paths is not a good idea
void main () {
//use function from ext here
printf ("app main func");
}
And then compile your application like this:
gcc app.c ext.c
and your test like this:
gcc test.c ext.c
In C, you can only have one definition of a function in all of the files you link into your executable. There's no good way to tell the compiler "I want to use this main() and not all the others". (There's a bad way, using macros, but it would be messy).
If you want to use a function with two different main() functions, put it in a separate file.
I suppose your compile/link call goes like
gcc test.c ext.c
In this case, test.c and ext.c (resp., to be exact, the .o files created out of them) are peers, i. e. on the same level. How should the linker know which version of the symbol main to take and which to discard? The linker doesn't know about the include files used.
In the case of a main function, the correct way to go is to have exactly one of them in your project.
For any other function where you have this requirement, there are several ways to go:
Either, you could declare one of them as "weak". It will be discarded when there is a "strong one".
Or you put your function into a library, e. g. libext.a. If you link that with -ext, only the object files which define symbols which are undeined are taken out of it. But then again, name clashes can occur if another name defined by that object file is defined already. So it is the best to only define as few symbols per object file as possible.

Global static function still working in another file

I declared a global static function in one file
a.c
static void Func1(void);
void Func2(void);
void Func1(void) {
puts("Func1 Called");
}
void Func2(void) {
puts("Func2 Called");
}
and accessed it in b.c
#include <stdio.h>
#include "a.c"
void main() {
Func1();
Func2();
}
the program complied successfully, but as per provided information this should give error: undefined reference to Func1. What wrong is happening here?
You don't include a source file in another, you compile and link them together.
In you case, by saying #include "a.c", you're essentially putting the whole content of a.c into b.c and then starting the compilation, so the static functions and their calls are present in the same translation unit. Thus, there is no issue for compiler to find the called function.
Instead, if you do something like
gcc a.c b.c -o a.out //try to compile and link together
you'll see the expected error, as in this case, a.c and b.c will be two separate translation units.
You declare in header files and define in .c files. So you must use header files to represent the variables or functions you defined. Instead if you use .c files then it leads to multiple definitions.I think that is why you can access that global function.

Linkage and static function confusion

I read that
A function with internal linkage is only visible to one compilation
unit. (...) A function declared static has internal linkage
For .c files it sorta makes sense, but I was wondering what happens with static functions in headers, which get included by multiple .c files but usually have an include guard.
I was reading this answer about static functions in headers, and the first item mentions that it doesn't create a symbol with external linkage and the second item mentions the function is available purely through the header file. Isn't that contradictory? How can the function be available and at the same time have no external symbol? So I did a little test:
/* 1.h */
#ifndef ONE_H
#define ONE_H
#include <stdio.h>
static void foo() {
printf("foo from 1.h %p\n", foo);
return;
}
void bar();
#endif
/* 1.c */
#include "1.h"
#include <stdio.h>
void bar() {
printf("foo,bar from 1.c %p,%p\n", foo, bar);
foo();
}
/* 2.c */
#include "1.h"
#include <stdio.h>
int main() {
printf("foo,bar from main %p,%p\n", foo, bar);
foo();
bar();
return 0;
}
...
debian#pc:~ gcc 2.c 1.c
debian#pc:~ ./a.out
foo,bar from main 0x400506,0x400574
foo from 1.h 0x400506
foo,bar from 1.c 0x400559,0x400574
foo from 1.h 0x400559
As expected bar is the same across all files, but shouldn't foo be too? Isn't 1.h included only once? Adding inline to foo resulted in the same behavior. I'm kinda lost.
Read here, how a header file basically works. That should clarify about your actual question.
Briefly: A header file is just inserted instead of the corresponding #include directive. So any declarations or definitions are treated by the compiler as if you actually copy/pasted the text into your file.
Anyway, you should be careful with function definitions in a header. This is deemed bad style in general. It blows the code for instance, creating redundant copies of that function. Also Function pointers cannot be compared (you never know ...). It is often better to bundle the functions into a library with just the declarations in a header (non-static then: external linkage). There are good justifications sometimes, however (no rule without exceptions). One of them are inline functions.
-static functions are functions that are only visible to other functions in the same file (more precisely the same translation unit).
Check this article for a detailed explanation on linkage: http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html

GCC/C++ cannot link libraries

I am just a beginner in C++. I am trying to construct some header file header.h, but the output is always like the following:
/tmp/ccTmZKXX.o: In function `main':
main.c:(.text+0x13): undefined reference to `func'
collect2: ld returned 1 exit status
Could you please help me to see whether my way of using header file is correct or not? Thanks a lot!
Main code (main.c):
#include "stdio.h"
#include "func.h"
main() {
double a = f(2.3);
printf("a=%f\n", a);
}
where func.c contains:
double func (double x) { return x ;}
where func.h contains:
double func (double);
And I compile with:
gcc -o main main.c
There are multiple problems here:
The C++ compiler in the GCC (GNU Compiler Collection) is g++, not gcc; the latter is the GNU C Compiler.
The code in main.c is a (not very good) C program and not a C++ program. C99 outlawed the implicit int return type; C++ essentially never allowed it.
Your question uses a function f; your compilation error references func. This means you did not show us exactly the code you tried to compile.
The standards say #include <stdio.h>; you should too.
#include <stdio.h>
#include "func.h"
int main()
{
double a = func(2.3);
printf("a=%f\n", a);
}
NB: This is a perfectly good C program if you work with C99. In C89, you are expected to return a value from main() rather than 'fall off the end'. C99 follows C++98 and allows falling off the end as equivalent to an explicit return 0;. I tend to put the explicit return(0); (usually with, sometimes without, the parentheses - the compilers don't mind either way) anyway. (I compile C with -Wstrict-prototypes; to get a warning-free compilation, I write int main(void), which also works with C++ but the void is not necessary there.)
The header is OK, though you will learn in due course about header guards and other paraphernalia that make headers more reliable.
#ifndef FUNC_H_INCLUDED
#define FUNC_H_INCLUDED
extern double func(double a);
#endif /* FUNC_H_INCLUDED */
The extern is not mandatory. I tend to use it, but there are many who do not.
The source file defining the function should include the header to ensure that the function definition is consistent with the declaration. All code that uses the function should include the header so that there is a prototype in scope. This cross-checking is crucial for reliability. C++ requires prototypes in scope before a function is used; it does not demand a prototype in scope before the function is defined (but it is good practice to do so). It is strongly recommended in C that you have a prototype in scope before defining an external (non-static) function. You can use -Wmissing-prototypes with C code and GCC to spot such problems, but the option is not valid for G++.
#include "func.h"
double func(double x) { return x; }
Since this is a C++ question, we could consider inlining the function in the header. Indeed, C99 also supports inline functions. However, we can ignore that for the time being.
Since this is a C++ question, we could consider that using <stdio.h> is not good because it is not type safe. You might be better off using <iostream> et al, not least because they are type safe.
#include <iostream>
#include "func.h"
int main()
{
double a = func(2.3);
std::cout << "a=" << a << std::endl;
}
The correct compilation requires both the main program and the function it invokes, so you might write:
g++ -o main main.c func.c
Or, if you are compiling it in C, then:
gcc -std=c99 -o main main.c func.c
Note that the -std=c99 is necessary to ensure that the absence of return in main() is acceptable.
Note that there are several extensions in use for C++ source code, including .C, .cpp and .cxx, all of which are accepted by G++ (as well as .c).
There are several things wrong here.
Define the function as follows in func.h
extern double func(double);
When compiling, provide all source (c, cpp) files
gcc main.c func.c -o main
You should be good to go.
Compile like this:
gcc -o main main.c func.c
Then it will be fine.

How do I use but not expose an inline function in a c99 library?

I'm writing a library in C99, and there are some parts of the library that would benefit significantly from the use of a macro / inline function. Inline functions are a better fit for my library.
However, very specifically I do not want to externally expose these inline functions.
Everything appears to work, but when I link against the library to create an executable I get the error: "undefined reference to `na_impl_gfx__draw'"
I have reproduced the problem to a minimal test case which does exactly what I do:
lib.h:
void somefunc();
lib.c:
#include <stdio.h>
#include "lib.h"
inline void someinline(char *value);
void somefunc() {
someinline("Hi!");
}
inline void someinline(char *value) {
printf("%s\n", value);
}
main.c:
#include "lib.h"
int main(int argc, char *argv[]) {
somefunc();
}
Now we compile:
doug#Wulf:~/test$ gcc -c -std=c99 lib.c
doug#Wulf:~/test$ gcc -c -std=c99 main.c
doug#Wulf:~/test$ gcc -std=c99 lib.o main.o
lib.o: In function `somefunc':
lib.c:(.text+0xe): undefined reference to `someinline'
lib.c:(.text+0x1a): undefined reference to `someinline'
lib.c:(.text+0x26): undefined reference to `someinline'
collect2: ld returned 1 exit status
It would appear that when compiling the library, the inline function is not being substituted into the object code for the function somefunc() in lib.h
Why?
The inline function is not externally visible. I would expect that when the library is compiled, the inline function is inlined into the function, just like the macro is (Nb. using only a macro this code compiles file).
What am I doing wrong? Or is this a restriction of inline functions?
The reason that you can't see the inline function in the same source file is that you haven't made them static.
All you need to do is make the prototype static with:
inline static void someinline(char *value);
and the function definition static with:
inline static void someinline(char *value) {
printf("%s\n", value);
}
[Sorry for kicking in as lately, you should have tagged your question with C and not only C99.]
I think with your question you are completely on the wrong track. Inline functions only make sense when you put them in a ".h" file. The whole concept is about making the function definition visible to all callers.
If you'd do so you should just put the definition (with the inline) in the header and an external declaration (with extern inline) in one compilation unit.
If you just want to have functions put in place in your "lib.o" compilation unit, forget about all that inline or static and let the compiler do that for you. gcc does that if you switch on optimization:
`-finline-small-functions'
Integrate functions into their callers when their body is smaller
than expected function call code (so overall size of program gets
smaller). The compiler heuristically decides which functions
are
simple enough to be worth integrating in this way.
Enabled at level `-O2'.

Resources