Linking my program using g++ - c++

I have some problems to build a program using g++. The program is using a library that I have written in C called libiec60063. I want to write my new project in C++ (even if not yet familiar with C++) but I can't manage to link it correctly.
For example I have the following code in a file called main.cpp
#include <libiec60063.h>
int main() {
Select_IEC60063_Number(125, 12);
return 0;
}
I can compile the source correctly typing
g++ -I/home/workspace/a_CommonBinary/include -c main.cpp
If I want to link it i get some error message
g++ -L/home/workspace/a_CommonBinary_draft/lib -o main main.o -lm -liec60063
main.o: In function `main':
main.cpp:(.text+0x1b): undefined reference to `Select_IEC60063_Number(double, int)'
collect2: error: ld returned 1 exit status
If I rename the main-file to main.c I can compile and link the program correctly with the GCC-Compiler using the same parameters.
Can anybody explain where there is a difference between gcc and g++?

You probably forgot to put
#ifdef __cplusplus
extern "C" {
#endif
near the beginning of your libiec60063.h header file, and
#ifdef __cplusplus
}; // end extern "C"
#endif
near the end of your header file, or if you don't want to change the header file:
extern "C" {
#include <libiec60063.h>
};
in your C++ code.
See this question. You need to disable name mangling. Read about compatibility of C & C++ .
BTW, you should compile with g++ -Wall -Wextra -g and perhaps with -std=c++11 and code for C++11

Related

Call a function in shared .so from C

My goal is creating a shared library created from c++. And I want to call a function in that library from a C program
I have a compareImage.h:
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
EXTERNC int compareTwoImages();
#undef EXTERNC
and a compareImage.cpp file:
#include "SURF_Homography.h"
extern "C" int compareTwoImages(){
..
}
I have already created a shared library by using this command:
g++ -ggdb `pkg-config --cflags opencv` -fpic -shared compareImage.cpp -o libcompareImage.so `pkg-config --libs opencv`
Then, I write a c program to call compareTwoImages() function from that shared lib like this:
#include <stdio.h>
int main() {
/* my first program in C */
int test = compareTwoImages();
printf("Comparison Results: %d\n", test);
return 0;
}
and compile it with this command:
gcc -lcompareImage c_call_cpp.c -o callCpp.o
But it shows an error:
/tmp/cc0wuZTU.o: In function `main':
c_call_cpp.c:(.text+0xe): undefined reference to `compareTwoImages'
collect2: error: ld returned 1 exit status
So I don't know what the problem is.
The problem is not with C++ or with your shared library or anything like that.
Narrow down your problem to a simple example next time.
Here you simply put the link flag in the wrong place:
gcc -lcompareImage c_call_cpp.c -o callCpp.o
# ^^^^^^^^^^^^^^
It needs to go after the object that'll use its symbols.
gcc c_call_cpp.c -o callCpp.o -lcompareImage
This is clearly stated in the documentation for -l:
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.

How to use C++ function from header in C?

I'm writing my thesis and I have problem with using C++ function in C code. I searched solution and I found a lot of them, but it didn't work anyway. Please explain it to me one more time.
To be quick I have something like below and after gcc main.c -o main I get undefined reference to 'cppfun'
cpp.h:
#pragma once
#ifdef __cplusplus
extern "C" {
#endi
void cppfun();
#ifdef __cplusplus
}
#endif
cpp.cpp:
#include <stdio.h>
#include "cpp.h"
void cppfun()
{
printf("cpp_fun");
}
main.c:
#include <stdio.h>
#indlude "cpp.h"
int main(int argc, char *argv[])
{
cppfun();
return 0;
}
When you combine C and C++, you should compile the translation unit containing the main function, as C++. Not opposite. This is a FAQ.
An undefined reference is usually because you haven't linked in the translation unit where the missing thing is. Your stated build command is
gcc main.c -o main
while it should be e.g.
gcc -c main.c
g++ -c cpp.cpp
g++ cpp.o main.o -o main
except as mentioned, the main translation unit should be in C++.
You need to include all .cpp files after main. Something like that:
g++ main.cpp other.cpp etc.cpp -o main
Firstly you compile your cpp code without link via -c compiler switch
g++ cpp.cpp -c
and you have cpp.o file then compile and link your main.c with cpp.h and cpp.o files via gcc
gcc main.c -o main cpp.o
I tested this answer via my linux server. It is work.

Linker error in switching from cc compiler to g++ compiler

I have been using C to code for sometime and I had no issues in compiling and linking my code to archive libraries (.a files). However, now I need to switch to C++ and doing so, I have to use g++ instead of cc for linking and compiling.
Using C, first thing to do was compiling the source and creating the object file and then linking it to the library using the same command but without the -c option:
cc -c -ggdb -Wall -Werror -I.. test.c -o test.o
cc -o test -ggdb -Wall -Werror test.o ../libpmem/libpmem.a
As I think the same procedure should be done for doing the same thing with g++, I tried to change the compiling and linking phase as follow:
g++ -c -ggdb -Wall -Werror -I.. test.c -o test.o
g++ test.o -I.. -L/path/libpmem -lpmem -o test
Although both sets should do the same thing, I always get an error while trying to link using g++. Here is the error message:
test.o: In function `main':
/path/test/test.c:5: undefined reference to `pmem_msync_mode()'
collect2: ld returned 1 exit status
make: *** [all] Error 1
There must be something wrong with the linking phase as the method definition must be found in the library file (just as the cc linker can find the definition and do the linking without any problem).
I also tried to do both linking and compiling using a single g++ command, but no matter what I do, I always get the same error. Any idea how can I fix this?
you probably have some sort of name mangling problem...
since it looks like that is declared in a c library there should already be some sort of
#ifdef __cplusplus
extern "C" {
#endif
int pmem_msync_mode();
#ifdef __cplusplus
}
#endif
but if there isn't in the library header you may have to do something like;
extern "C" {
#include <pmem.h>
}
See http://www.cplusplus.com/forum/general/1143/
You need to tell the compiler that the code is compiled as C
I am assuming that the pmem library is compiled and linked as C code.
C and C++ have different conventions for how they store the names of functions in binary format. See http://en.wikipedia.org/wiki/Name_mangling for a reference.
To solve your problem, probably the solution is to:
extern "C" {
#include <pmem.h>
}
When the C++ compiler imports the function declarations from the header, without external C linkage being specified, it expects the binary it links against to have the associated functions' representations in a different format, namely whatever format your C++ compiler mangles function names to.

Link .o (C object file) to C++ file/project on Linux

I have a problem with .o file in linux as follow:
I have Visual.cpp which call function ECL_Drawrect() and this function is defined as:
#define ECL_Drawrect ECL_bDrawrect
In my Visual.cpp I also include "ecl.h" as:
#include "ecl.h"
int main() {
ECL_Drawrect (0,0,20,20,false);
return 0;
}
The problem is that the function ECL_bDrawrect is in the ecl.o file and i don't know how to link it to use the function mentioned above.
After some research I figured out and setup as follow:
g++ Visual.cpp -o Visual /usr/include/ecl.o
The ecl.o path also incluced in my project and when I compiled i get this error:
**** Build of configuration Debug for project Visual ****
make all
Building file: ../src/Visual.cpp
Invoking: GCC C++ Compiler
g++ -m32 -O0 -g3 -Wall -c -fmessage-length=0 /usr/include/ecl.o -MMD -MP -MF"src/Visual.d" -MT"src/Visual.d" -o "src/Visual.o" "../src/Visual.cpp"
g++: /usr/include/ecl.o: linker input file unused because linking not done
Finished building: ../src/Visual.cpp
Building target: Visual
Invoking: GCC C++ Linker
g++ -m32 -o "Visual" ./src/Visual.o
/usr/bin/ld: ./src/Visual.o: in function main:../src/Visual.cpp:7: error: undefined reference to 'ECL_bDrawrect'
collect2: ld returned 1 exit status
make: *** [Visual] Error 1
**** Build Finished ****
I don't know whether the link is correct or not? How can I link this ecl.o file in properly way?
p/S: I'm using eclipse CDT in ubuntu 11.04 64-bit and the ecl.o is for 32-bit, that's why I have to put -m32 to g++.
The ecl.o file is not listed on the linker command line.
Also, you probably need to use extern "C" around the include:
extern "C" {
#include "ecl.h"
}
Is it possible that the problem is C++ name mangling? Maybe declaring your functions as extern "C" it will work.
#ifdef __cplusplus
extern "C" {
#endif
/* ... */
#ifdef __cplusplus
}
#endif

g++ linking issue

I have a dependancy library (libfcgi) that I compiled with g++ (GCC v4.4 MinGW) using the following calls:
g++ -Iinclude -c -O2 *.c
ar rcs ../libfcgi.a *.o
Now, my main project is built like so:
g++ -Idependancies\libfcgi\include -Ldependancies -O2 -lfcgi *.cpp
g++ apparently finds libfcgi.a, but yet it fails to link to the following references:
'FCGI_printf'
'FCGI_Accept'
In the libfcgi sources, these functions are defined as follows:
#ifdef __cplusplus
extern "C" {
#endif
//...
DLLAPI int FCGI_printf(const char *format, ...);
DLLAPI int FCGI_Accept(void);
//...
#ifdef __cplusplus
}
#endif
where DLLAPI is nothing (as it isn't compiled as a shared library) and __cplusplus is defined (g++).
Looking at libfcgi.a, those functions are exported as '_FCGI_Accept' and '_FCGI_printf', so with an underscore in front. That's what seems to hinder g++ to find them.
I thought using export "C" would suffice to link to a C function in C++, so what am I doing wrong?
Thanks :)
If you have the same extern "C" definitions in your .cpp sources, then I think your problem is that the -lfcgi should follow the *.cpp in your command line:
g++ -Idependancies\libfcgi\include -Ldependancies -O2 *.cpp -lfcgi
In your main-project, you tell the compiler to link C-functions, due to the extern "C". It therefore expects unmangled symbol-names. You should therefore compile the fcgi-library with the C compiler, not the C++ compiler.