Writing/Using C++ Libraries - c++

I am looking for basic examples/tutorials on:
How to write/compile libraries in C++ (.so files for Linux, .dll files for Windows).
How to import and use those libraries in other code.

The code
r.cc :
#include "t.h"
int main()
{
f();
return 0;
}
t.h :
void f();
t.cc :
#include<iostream>
#include "t.h"
void f()
{
std::cout << "OH HAI. I'M F." << std::endl;
}
But how, how, how?!
~$ g++ -fpic -c t.cc # get t.o
~$ g++ -shared -o t.so t.o # get t.so
~$ export LD_LIBRARY_PATH="." # make sure t.so is found when dynamically linked
~$ g++ r.cc t.so # get an executable
The export step is not needed if you install the shared library somewhere along the global library path.

Related

how to make library from c++ class files (.cpp/.h) so that this can be included in other programs as #include <cplong>?

for cplong class files are cplong.cpp/cplong.h in github.com/zava8/plong --- src/
i have tested these classes in main.cpp . it is working fine?
now i am trying for including cplong as library in other programs as:
#include
for this i created makefile as :
viml#viml ~/maigit/eclp/plong $ cat src/makefile
NAME=libplong.so
CPPFLAGS=-g -o $(NAME) -fPIC -shared
FILE=cplong.cpp
$(NAME): $(FILE)
g++ $(FILE) $(CPPFLAGS)
and install.sh as :
viml#viml ~/maigit/eclp/plong $ cat src/install.sh
#!/bin/bash
echo "building and installing cplong library."
make
sudo mv libplong.so /usr/lib/
sudo cp cplong.h /usr/include/
echo "finished installing. to use library, add '-lplong' as a flag"
after that i try to use this in other programs (say uzeplong.cpp) as :
// github.com/zava8/plong uze_kesiz/uzeplong.cpp
#include <cplong.h>
#include <iostream>
using namespace std;
int main() {
cplong a(0x5C, -1);
cout << "a is: " << a << endl; // out should be 5.C (heks plong)
return 0;
}
after this compiling as :
g++ -lplong uzeplong.cpp
when compiling getting errors as undefined reference .....
so i need help to create and use library from c++ class (*.cpp and *.h)?
cplong.cpp and cplong.h are in github.com/zava8/plong src/

Separate instance of static variable in static library for shared library

Consider the following setup consisting of two shared libraries which both use a static library:
static.cpp
#include "static.h"
static int a = 0;
int getA()
{
return a++;
}
static.h
#pragma once
int getA();
shareda.cpp
#include <iostream>
#include "shareda.h"
#include "static.h"
void printA()
{
std::cout << getA() << std::endl;
}
shareda.h
#pragma once
void printA();
sharedb.cpp
#include <iostream>
#include "sharedb.h"
#include "static.h"
void printB()
{
std::cout << getA() << std::endl;
}
sharedb.h
#pragma once
void printB();
main.cpp
#include "shareda.h"
#include "sharedb.h"
int main()
{
printA();
printA();
printB();
printA();
printB();
return 0;
}
I compiled and ran these files with the following commands (using Clang 3.8.0, compiled from source, and 64-bit Debian with GNU ld 2.25):
clang++ -c static.cpp -o static.o -fPIC
ar rcs libstatic.a static.o
clang++ -c shareda.cpp -o shareda.o -fPIC
clang++ -shared -o libshareda.so shareda.o libstatic.a
clang++ -c sharedb.cpp -o sharedb.o -fPIC
clang++ -shared -o libsharedb.so sharedb.o libstatic.a
clang++ -L. -lshareda -lsharedb -o main main.cpp
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
To my surprise, the output was the following:
0
1
2
3
4
My expectation was this:
0
1
0
2
1
Apparently, despite the static keyword in front of a in static.cpp, only one instance of a exists. Is there a way to have two instances of a, one for each of the shared libraries?
Apparently, despite the static keyword in front of a in static.cpp, only one instance of a exists.
That is incorrect: two instances of a exist, but only one is actually used.
And that is happening because (contrary to your expectations) printB calls the first getA available to it (the one from libshareda.so, not the one from libsharedb.so). That is one major difference between UNIX shared libraries and Windows DLLs. UNIX shared libraries emulate what would have happened if your link was:
clang++ -L. -o main main.cpp shareda.o sharedb.o libstatic.a
So what can you do to "fix" this?
You could link libsharedb.so to prefer its own getA, by using -Bsymbolic.
You could hide getA inside libsharedb.so completely (as if it's a private implementation detail):
clang++ -c -fvisibility=hidden -fPIC static.cpp
ar rcs libstatic.a static.o
clang++ -shared -o libsharedb.so sharedb.o libstatic.a
You could achieve similar result using linker version script.
P.S. Your link command:
clang++ -L. -lshareda -lsharedb -o main main.cpp
is completely backwards. It should be:
clang++ -L. -o main main.cpp -lshareda -lsharedb
The order of sources/object files and libraries on command line matters, and libraries should follow object files that reference them.

OS X 10.9: cannot debug c++ dynamic library made with g++

I've read multiple posts here relating to dynamic libraries on os x and debugging with gdb. But I still can't figure out why I can't debug a simple test case.
The main issue is that when I start up GDB it never loads any shared libraries.
Update: I've tried this with GDB from macports, from homebrew, and built from source and the behavior is the same.
I have a class that I compile into a library.
Test.hpp
class Test {
public:
void set(int i);
void out() const;
private:
int i;
};
Test.cpp
#include "Test.hpp"
#include <iostream>
void Test::set(int ii) { i = ii; }
void Test::out() const {
auto j = i * 100;
std::cout << i << ", " << j << "\n";
++j;
std::cout << i << ", " << j << "\n";
}
I compile it and create a library with g++. Note: the behavior is the same with macports gcc and the gcc from xcode.
/opt/local/bin/g++-mp-4.8 -O0 -g -ggdb -Wall -c -std=c++11 -o Test.o Test.cpp
/opt/local/bin/g++-mp-4.8 -dynamiclib -o libTest.dylib Test.o
Then I test it with this simple main
#include "Test.hpp"
int main() {
Test t;
auto x = 4;
t.set(x);
t.out();
return 0;
}
This is compiled and linked with
/opt/local/bin/g++-mp-4.8 -O0 -g -ggdb -Wall -c -std=c++11 -o main.o main.cpp
/opt/local/bin/g++-mp-4.8 -L . -o testing main.o -lTest
Everything compiles and runs as expected. But when I try to debug this with gdb (installed from macports, or installed from source, the behavior is the same), I have problems.
As I step through main, if I call info sharedlibrary it always says "No shared libraries loaded at this time.", so it apparently never loads libTest.dylib. Therefore, I can't step into any of the Test member functions or create breakpoints anywhere in libTest.dylib.
Indeed ggdb installed from macports for some reason does not respect the DYLD_LIBRARY_PATH. However, if you "patch" your executable with the correct paths for the .dylibs you should be able to debug with ggdb. Take a look at this question and especially the answer by Akos Cz.

Compile shared object library, which call function from so too

I have got a f2.cpp file
// f2.cpp
#include <iostream>
void f2()
{
std::cout << "It's a call of f2 function" << std::endl;
}
I use cygwin with crosstool compiler gcc.
g++ -fPIC -c f2.cpp
g++ -shared -o libf2.so f2.o
I have got a libf2.so file. Now I want to call f2 function in f1 library (shared object too) libf1.so.
It's a f1.cpp and i want take f1.so
// f1.cpp
#include <iostream>
void f1()
{
std::cout << "f1 function is calling f2()..." << std::endl;
f2();
}
How i must compile f1.cpp? I don't want to use dlclose, dlerror, dlopen, dlsym...
Аt last i want to use f1.so in main.cpp as a shared object library too... without using use dlclose, dlerror, dlopen, dlsym. How I must compile main.cpp, when i will have a f1.so ?
// main.cpp
#include <iostream>
int main()
{
f1();
return 0;
}
declare f2() in a header file. and compile libf1.so similar to libf2.
Now compile main linking against f1 and f2.
It should look something like this
g++ -lf2 -lf1 -L /path/to/libs main.o
You can simply link them together (if f2 is compiled into libf2.so, you pass -lf2 to the linker). The linker will take care of connecting calls from f1 to f2. Naturally, at runtime f1 will expect to find f2 in the SO load path and the dynamic loader will load it.
Here's a more complete sample, taken from a portion of a Makefile I found lying around. Here, mylib stands for your f2, and main_linked is f1:
mylib: mylib.c mylib.h
gcc $(CFLAGS) -fpic -c mylib.c
gcc -shared -o libmylib.so mylib.o
main_linked: main_linked.c mylib.h mylib.c
gcc $(CFLAGS) -L. -lmylib main_linked.c -o main_linked
Note:
mylib is compiled into a shared library with -shared
main_linked is then built with a single gcc call passing -lmylib to specify the library to link and -L. to say where to find it (in this case - current dir)
Check the -L and -l flags to g++.

LD_PRELOAD help

I'm trying to use LD_PRELOAD.
original.cpp
void myPuts() {
puts ("Hello myPuts");
}
int main() {
myPuts();
return 0;
}
hacked.cpp
void myPuts() {
std::cout >> "Hello hacked myPuts";
}
I compile original.cpp:
g++ original.cpp
And hacked.cpp:
g++ -shared -fPIC hacked.cpp
I try:
LD_PRELOAD=./hacked.so ./original.out
The string "Hello hacked myPuts" should be seen, by "Hello myPuts" appears.
(If I try to "overwrite" the puts function, it works correctly)
What am I missing?
From man ld.so
LD_PRELOAD
A whitespace-separated list of additional, user-specified, ELF shared libraries to be loaded before all others. This can be used to selectively override functions in other shared libraries.
If myPuts was in shared library linked to main application it would work, but not when
myPuts exists in the application and does not resolved in an external library.
You should have:
main.cpp
int main() {
myPuts();
return 0;
}
original.cpp
void myPuts() {
puts ("Hello myPuts");
}
hacked.cpp
void myPuts() {
std::cout << "Hello hacked myPuts";
}
Compiling all:
g++ -shared -fPIC original.cpp -o liboriginal.so
g++ -shared -fPIC hacked.cpp -o libhacked.so
g++ main.cpp -loriginal -o main.out
And using:
LD_PRELOAD=./libhacked.so ./main.out