GCC/C++ cannot link libraries - c

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.

Related

At what point during compilation or linking of C code are extern variables implicitly defined?

If I have a project with the following 3 files in the same directory:
mylib.h:
int some_global;
void set_some_global(int value);
mylib.c:
#include "mylib.h"
void set_some_global(int value)
{
some_global = value;
}
main.c:
#include <stdio.h>
#include "mylib.h"
int main()
{
set_some_global(42);
printf("Some global: %d\n", some_global);
return 0;
}
and I compile with
gcc main.c mylib.c -o prog -Wall -Wpedantic
I get no errors or warnings, and the prog program prints 42 to the console.
When I first tried this, I expected there to be a "multiple definition" error or some kind of warning since some_global is not declared extern in the header file. Upon researching this issue, I discovered that in C the extern is implicit on variable declarations outside of functions (and also that the opposite is true for C++, which can be demonstrated by using g++ instead of gcc in the compilation line above). Also, if I change the line in mylib.h from a declaration to a definition (e.g. int some_global = 1;), I do get the "multiple definition" error that I expected (this is nothing shocking).
My main question is: where is the variable being defined? It appears to be implicitly defined somewhere, but at what point does either the compiler or linker realize it needs that variable defined and does so?
Also, why is it that if I explicitly declare the variable as extern in the mylib.h file, I get "undefined reference" errors unless I explicitly declare the variable in one and only one *.c? I would expect that given the reason why the code above works (that extern is implicit), that explicitly declaring extern wouldn't make a difference. Why is there a difference in behavior?
Follow up
After the answer below corrected me that the code in mylib.h is a "tentative definition" rather than a declaration, I discovered this related answer with more details on such matters:
https://stackoverflow.com/a/3095957/7007605
Your code compiles and links without error only because you use gcc which was compiled with -fcommon command line option "The -fcommon places uninitialized global variables in a common block. This allows the linker to resolve all tentative definitions of the same variable in different compilation units to the same object, or to a non-tentative definition. (...) It is mainly useful to enable legacy code to link without errors." This was default prior to version 10, but even now many toolchains are still build with this option enabled.
Never define data in the header files. Place only extern definitions of the variables in the header files.
It should be:
extern int some_global;
void set_some_global(int value);
mylib.c:
#include "mylib.h"
int some_global;
void set_some_global(int value)
{
some_global = value;
}
main.c:
#include <stdio.h>
#include "mylib.h"
int main()
{
set_some_global(42);
printf("Some global: %d\n", some_global);
return 0;
}
int some_global; is a tentative definition. In GCC before version 10, GCC produced an object file treating this as a common symbol. (This behavior is still selectable by a switch, -fcommon.) The linker coalesces multiple definitions of a common symbol to a single definition.

Why do I need to declare this function extern. It works without it

I am new to the concept of extern. Today at work I came across a large number of extern functions that were declared inside of header file; foo.h. Somewhere off in a mess of folders I found a foo.c file that contained the definition of said functions but it did not #include foo.h. When I got home I decided to play around with the extern storage class examples. After doing some reading in the "C book" this is what I came up with.
Here is what I DID NOT expect to work. But it did.
main.c
#include <stdio.h>
int data;
int main()
{
data = 6;
printf("%d\n", getData());
data = 8;
printf("%d\n", getData());
return 0;
}
externs.c
int getData()
{
extern int data;
return data;
}
bash
gcc main.c externs.c -o externs
I didn't think this would work because the function is not technically (or at least verbose) defined before main. Does this work because the default storage class for int getData() is extern? If so, why even bother with the following example (similar to what I saw at work)?
main2.c
#include <stdio.h>
#include "externs.h"
int data;
int main()
{
data = 6;
printf("%d\n", getData());
data = 8;
printf("%d\n", getData());
return 0;
}
externs.h
#ifndef _EXTERNSH_
#define _EXTERNSH_
extern int getData();
#endif
externs.c
int getData()
{
extern int data;
return data;
}
bash
gcc main2.c externs.c -o externs
Functions are implicitly extern. You can change this by declaring them as static.
You are right that it is redundant to say extern int getData(); compared to int getData(); but some people feel that it improves code clarity.
Note that since C99, your first example is ill-formed. It calls getData without that function having been declared. In C89 this performed an implicit int getData(); declaration, but since C99 that was removed. Use the compiler switches -std=c99 -pedantic to test this.
By default, GCC version 4.x or earlier compiles in a C89/C90 compatibility mode, which does not require functions to be declared before use. Undeclared functions are inferred to have a return type of int. By default, GCC 5.x or later compiles in C11 compatibility mode, which does require functions to be declared before use — as does C99.
Given that the code compiled without complaints, we can infer that you are using GCC 4.x.
Even so, you are not obliged to provide full prototypes, though you would be foolish not to. I routinely compile code with the options:
gcc -std=c11 -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Wold-style-declaration …
I suspect that there is some redundancy in there, but those options catch many problems before I get around to running the code.

Calling C++ Application Code from C library?

Folks, Assuming I have a c++ application / library running which implements say
/* Alloc API */
void* my_alloc(int size) {
return malloc(sizeof(size));
}
This is not under "extern c".
I have a C dynamic library from which I need to call my_alloc, can I directly call that API?
Like,
int test_my_alloc (int size) {
int *x;
x = (int*)my_alloc(size);
if (x == NULL) {
return 0;
} else {
return 1;
}
}
You need to create a stub, e.g.
Stub header:
// stub.h
#ifdef __cplusplus
extern "C" {
#endif
void* my_alloc_c(int size);
#ifdef __cplusplus
}
#endif
Stub implementation:
// stub.cpp
#include "stub.h"
#include "header_where_my_alloc_is_declared.h"
void* my_alloc_c(int size)
{
return my_alloc(size);
}
Your C code (example):
// my_code.c
#include "stub.h"
int main()
{
void * p = my_alloc_c(42);
return 0;
}
Then compile your stub and link it with your C code:
g++ -Wall -c stub.cpp # compile stub.cpp
gcc -Wall my_code.c stub.o # compile your C code and link with stub.o
As Paul R. answered, you need a stub code. also, you'll better be sure that your C++ function does not throw exceptions (I guess that a C++ function, called from a C program and main, which throws an uncaught exception is having some undefined behavior). BTW, you should be sure that the constructor of static C++ data (like std::cout) is called "conceptually" before your main in C (so you better link your program with a C++ compiler, not a C one). See the GCC __attribute__(constructor)
In practice, at least on Linux with C++ code compiled by GCC (g++) or by Clang/LLVM (clang++), a C++ function has some mangled name.
You might use some ugly and non-portable trick to call a function by its mangled name. You could dare coding:
int main(int argc, char**argv) {
extern void* _Z10my_alloc_ci(int size);
void * p = _Z10my_alloc_ci(42);
return 0;
}
but I am a bit ashamed of giving such silly advice. You could even use asm labels e.g.
extern void*f(int) asm ("_Z10my_alloc_ci");
p = f(42);
However, I feel that you should not have any such approaches, and I am surprized why you need to call a C++ function which is not wrapped around extern "C".
Notice that in theory, C++ functions (without extern "C") could even have a different -and incompatible- calling convention than C functions. I don't know any implementation doing that. So to be safe you should wrap your C++ function with some C++ wrapping using extern "C"
To avoid uncaught exceptions, you might catch all of them in your C++ wrapper:
#include <cstdio>
#include <cstdlib>
extern "C" void* my_alloc_c(int size) {
extern void* my_alloc(int);
try {
return my_alloc(size);
} catch (...) {
::fprintf(::stderr, "got uncaught C++ exception for my_alloc(%d)\n",
size);
::fflush(nullptr);
::abort();
}
}
BTW, if your C++ library is large, you might perhaps try to automatize the generation of the glue code. For example, you could customize GCC using MELT (a Lispy domain specific language to extend GCC) by coding an extension in MELT which would generate the glue code when compiling the C++ header files.
You might be interested in libffi which enables you to (portably) call any (C and probably C++) function of arbitrary signature.
From what I gathered:
You have a C++ library you have no control over (you can't add the extern "C")
You have a C library that must call the C++ library
You can modify your C library to accommodate a solution (you can change the makefile and change the name of the function you want to call)
So, one alternative solution would be to compile your C library with the very same C++ compiler used for that C++ library, if that's acceptable for you.
Note: with C89, you'll possibly need to modify bits of your code (e.g. void * to T * conversions are not implicit anymore in C++), but it would probably be easier than 100+ wrappers.
Note 2: If you're using some C99 features (e.g. the VLAs), then that code will not compile in C++.

Default function implementation for linking

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() { /* ... */ }

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