Embedding libmicrohttpd code in C++ OR how to compile this example? - c++

I have a requirement of creating a C++ program which exposes certain functions through HTTP. For that reason I was trying to use libmicrohttpd for the same. Now this library is written in C. However I am kind of new to C++ and am trying to compile this C and C++ code given here. (Which can be git cloned from here)
Now I need help in understanding how g++ may be used to compile a program which is not written completely in C++. And/or how to compile the above linked code.
PS: Working in linux
And finally if someone can point to an easier alternative than libmicrohttpd - I am all ears.
Edit to Edit:
Finally got it working. Compiled the individual cpp files with gcc and then linked everything using g++. I have no clue how this came to work, maybe some one can reply below.
I have made the following script to compile and link:
LOC="path/to/directory"
gcc -c httphandler.cpp -o httphandler.o -I $LOC
gcc -c strutil.cpp -o strutil.o -I $LOC
gcc -c api.cpp -o api.o -I $LOC
gcc -c executor.cpp -o executor.o -I $LOC
g++ -o out httphandler.o strutil.o api.o executor.o -lmicrohttpd -lboost_regex
But in the final step I am getting the following error:
/usr/bin/ld: strutil.o: undefined reference to symbol '__cxa_free_exception##CXXABI_1.3'
/usr/bin/ld: note: '__cxa_free_exception##CXXABI_1.3' is defined in DSO /usr/lib/x86_64-linux-gnu/libstdc++.so.6 so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libstdc++.so.6: could not read symbols: Invalid operation
What gives?

For starters, don't compile the C code with g++, use gcc instead. Then just include the header file and use the functions normally. When linking don't forget to link with the object file(s) generated from compiling the libmicrohttpd source file(s).

Related

How can I make sure `iostream` is available to the linker?

I have the following C++ code in a file called helloworld.cpp:
#include<iostream>
int main()
{
std::cout << "Hello, World!\n";
}
I would like to compile this manually so I can really understand how the compilation steps work with gcc, namely:
Preprocessing
Compilation
Assembly
Linking
This article gives some useful information about how to break up the compilation steps. And so I came up with the following:
Preprocessing
cpp helloworld.cpp > helloworld.i
Compilation
g++ -S helloworld.i
Assembly as -o helloworld.o helloworld.s
Linking
ld -o helloworld helloworld.o
Everything seems to work except for the last step, as outlined by the article:
ld -o hello hello.o ...libraries...
The libraries argument above is a long list of libraries that you need to find out. I omitted the exact arguments because the list is really long and complicated, and depends on which libraries g++ is using on your system. If you are interested to find out, you can run the command g++ -Q -v -o hello hello.cpp and take a look at the last line where g++ invokes collect2
And so I tried running g++ -Q -v -o helloworld helloworld.cpp, but the result is extremely verbose.
I'm still unsure how to complete ld such that iostream can be available to the linker when I invoke it. How can I make sure iostream is available to the linker?
I'm still unsure how to complete ld such that iostream can be available to the linker when I invoke it.
You should never use ld to link any user-level programs, only when you are linking something esoteric, like an OS kernel or a boot loader.
Instead, (for user-level program) always use appropriate compiler driver (g++ here).
While you can find out how the compiler driver eventually invokes ld internally (e.g. using strace -fe execve -s 1024 g++ ...), note that that command may change from version to version, and depends on a multitude of flags (-pie vs. -no-pie, -shared, -static etc.) and you chances of continuing to use correct ld command after a few months are nil.
Based on the comments and posted answer I realized that the blog from which I was copying those commands makes things more complicated than they really need to be for my purposes. It's definitely possible to isolate every step of the compilation process using solely the g++ command. Here's a Makefile I came up with:
all: preprocess compile assemble link
# helloworld.i contains preprocessed source code
preprocess:
#echo "\nPREPROCESSING\n"; g++ -E -o helloworld.i helloworld.cpp
# compile preprocessed source code to assembly language.
# hello.s will contain assembly code
compile:
#echo "\nCOMPILATION\n"; g++ -S helloworld.i
# convert assembly to machine code
assemble:
#echo "\nASSEMBLY\n"; g++ -c helloworld.s
# links object code with the library code to produce an executable
# libraries need to be specified here
link:
#echo "\nLINKING\n"; g++ helloworld.o -o test
clean:
#find -type f ! -name "*.cpp" ! -name "*.h" ! -name "Makefile" -delete
Now I can compile my C++ programs in such a way that I can track whether the preprocessor, compiler, assembler or linker is generating the error.

C++ file compiling: -L and -I arguments don't work for boost library

There are similar questions but their answers did not work for my issue.
I have a c++ program with #include <boost/test/unit_test.hpp> on top (among other includes).
To compile correctly, if I understood, I should do the command:
g++ -g -L/path_to_boost_lib -lboost_lib myprog.cpp -o myprog.exe
If i do a locate, I get /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.so.
Hence I edited my call to g++ by doing:
g++ -g -L/usr/lib/x86_64-linux-gnu -lboost_unit_test_framework myprog.cpp -o myprog.exe
But I still get errors of the type undefined reference to boost::unit_test.
I also tried the option -I/usr/include/ which contains the boost folder, without success.
It's because of the order. The GCC linker goes through the artifacts left-to-right, and every unknown symbol it encounters in an object file must be resolved by an artifact occurring afterwards.
The right command is thus:
g++ -g myprog.cpp -L/usr/lib/x86_64-linux-gnu -lboost_unit_test_framework -o myprog.exe
See this answer for a more thorough explanation.
I suggest using a build tool like CMake that takes care of such low-level details for you.

undefined reference to \ `__gxx_personality_seh0' and collect2.exe: error: ld returned 1 exit status [duplicate]

I've been getting this undefined symbol building with this command line:
$ gcc test.cpp
Undefined symbols:
"___gxx_personality_v0", referenced from:
etc...
test.cpp is simple and should build fine. What is the deal?
Use
g++ test.cpp
instead, since this is c++ code.
Or, if you really want to use gcc, add -lstdc++ to the command line, like so:
gcc test.cpp -lstdc++
Running md5 against the a.out produced under each scenario shows that it's the same output.
But, yeah, g++ probably makes your world a simpler place.
The .cpp extension causes gcc to compile your file as a C++ file. (See the GCC docs.)
Try compiling the same file, but rename it to have a .c extension:
mv test.cpp
gcc test.c
Alternatively, you can explicitly specify the language by passing -x c to the compiler:
gcc -x c -c test.cpp -o test.o
If you run nm test.o on these C-language versions, you'll notice that ___gxx_personality_v0 is not listed as a symbol.
(And if you run the same command on an object file generated with gcc -c test.cpp -o test.o, the ___gxx_personality_v0 symbol is present.)
Just in case anyone has the same problem as me: The file extension should be a .c not a .C (gcc is case-sensitive).
Had the same problem, but a different solution:
C++ code in static library getting linked, and being referenced by a .m file. Renaming the .m file to .mm fixed the issue.

C++ Map Initialization throws .text Error [duplicate]

I've been getting this undefined symbol building with this command line:
$ gcc test.cpp
Undefined symbols:
"___gxx_personality_v0", referenced from:
etc...
test.cpp is simple and should build fine. What is the deal?
Use
g++ test.cpp
instead, since this is c++ code.
Or, if you really want to use gcc, add -lstdc++ to the command line, like so:
gcc test.cpp -lstdc++
Running md5 against the a.out produced under each scenario shows that it's the same output.
But, yeah, g++ probably makes your world a simpler place.
The .cpp extension causes gcc to compile your file as a C++ file. (See the GCC docs.)
Try compiling the same file, but rename it to have a .c extension:
mv test.cpp
gcc test.c
Alternatively, you can explicitly specify the language by passing -x c to the compiler:
gcc -x c -c test.cpp -o test.o
If you run nm test.o on these C-language versions, you'll notice that ___gxx_personality_v0 is not listed as a symbol.
(And if you run the same command on an object file generated with gcc -c test.cpp -o test.o, the ___gxx_personality_v0 symbol is present.)
Just in case anyone has the same problem as me: The file extension should be a .c not a .C (gcc is case-sensitive).
Had the same problem, but a different solution:
C++ code in static library getting linked, and being referenced by a .m file. Renaming the .m file to .mm fixed the issue.

C++ multi-stage linking

Ok, so this might not be a great question, but I'm a bit stuck.
I have 3 programs:
pegio.c/pegio.h - Does hardware initialization and functions for my device
PegIOHandler.cpp/PegIOHandler.h - Handles I/O for device
PegRTU.cpp - Main function
My project implements the opendnp3 (which allows one to transmit data using the DNP3 protocol) library.
Now, to compile it I first compile the pegio.c file
gcc -c pegio.c -o pegio.o
Easy, up to here I understand.
Secondly I compile the IOHandler and reference pegio.c as it uses it.
g++ -c PegIOHandler.cpp pegio.c -o PegIOHandler.o -std=c++0x
Now it gives me the following output.
g++: warning: pegio.o: linker input file unused because linking not done
But, it still creates the object file. HOWEVER, PegIOHandler implements opendnp3 header files, which is included in PegIOHandler.cpp and PegIOHandler.h. When I attempt to compile these files without using the '-c', it tells me that there are undefined references to the opendnp3 files. I know I have to link them to my project, but how do I do that?
Then compililing my third and final file:
g++ PegRTU.cpp pegio.o PegIOHandler.o -o pegrtu -std=c++0x
This now tells me that there are undefined references to the opendnp3 files.
So: How do I link the opendnp3 library to my project / code files???
Thanks!
Ouch. So many misunderstandings. You don't need the previously compiled object files to compile further source files to object code. However, you do need to link them together at the end of the compilation process, including any libraries required. All in all:
gcc -c pegio.c -o pegio.o
g++ -c PegIOHandler.cpp -o PegIOHandler.o -std=c++0x
g++ -c PegRTU.cpp -o PegRTU.o -std=c++0x
g++ -o executable_name *.o -lopendnp3 # or whatever linker flag is needed for OpenDNP3
And pretty please, read this.