I just started programming in C++ and I've realized that I've been having to write the same code over and over again(mostly utility functions).
So, I'm trying to create a shared library and install it in PATH so that I could use the utility functions whenever I needed to.
Here's what I've done so far :-
Create a file utils.h with the following contents :-
#include<iostream>
#include<string>
std::string to_binary(int x);
Create a file utils.cpp with the following contents :-
#include "utils.h"
std::string to_binary(int x) {
std::string binary = "";
while ( x > 0 ) {
if ( x & 1 ) binary += "1";
else binary += "0";
x >>= 1;
}
return binary;
}
Follow the steps mentioned here :-
http://www.techytalk.info/c-cplusplus-library-programming-on-linux-part-two-dynamic-libraries/
Create the library object code : g++ -Wall -fPIC -c utils.cpp
But as the link above is meant for Linux it does not really work on OSX. Could someone suggest reading resources or suggest hints in how I could go about compiling and setting those objects in the path on an OSX machine?
Also, I'm guessing that there should be a way I can make this cross-platform(i.e. write a set of instructions(bash script) or a Makefile) so that I could use to compile this easily across platforms. Any hints on that?
Use -dynamiclib option to compile a dynamic library on OS X:
g++ -dynamiclib -o libutils.dylib utils.cpp
And then use it in your client application:
g++ client.cpp -L/dir/ -lutils
The link you posted is using C and the C compiler. Since you are building C++:
g++ -shared -o libYourLibraryName.so utils.o
Related
Let me first set the context, it is CERN's ROOT and CINT and ACLiC etc.
Suppose I have a main macro named macro.cpp and two headers h1.cpp (contains the definition of a function) and h1.h containing the declaration of the function defined in h1.cpp similarly I have h2.cpp and h2.h. The main program macro.cpp calls those functions inside h1 and h2. I was successful compiling the source files using:
root [0] .L h1.cpp+
root [1] .L h2.cpp+
root [2] .L macro.cpp+
which generated three .so files macro_cpp.so, h1_cpp.so and h2_cpp.so. I want to know what to do with them ? How do I link them so that I have something like a "macro.out" or something like that (a single executable file of some kind) which I can execute (although I don't know how !) and achieve whatever I wished to achieve with the macro.
Note: If I just load all the files using .L file_name.cpp etc and just execute the main macro using .x macro.cpp then everything works fine and I have results, but this is not what I want ! I want to compile like we do in usual g++ and by the way in every forum everyone keeps advising on compiling using .L file_name.cpp+ or ++ .. I would really like to know the whole story. Because nobody seems to explain beyond .L file_name.cpp+ .. what next ? What to do with the .so etc.
I am a beginner, I will really appreciate a simple and step by step answer and explanation.
Thanks.
Edit-1: I am working with:
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Edit-2: ROOT related information:
ROOT 5.34/36 (v5-34-36#v5-34-36, dic 07 2016, 23:31:51 on linuxx8664gcc)
CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010
If you want to compile and link you can use a standard compiler instead of Cint/Aclic.
For example, assuming you are working on a *nix platform, you can use the example files below:
h1.h
int add_one(int a);
h1.cpp
#include "h1.h"
int add_one(int a)
{
return a+1;
}
h2.h
#include <TLorentzVector.h>
TLorentzVector multiply_by_two(const TLorentzVector v);
h2.cpp
#include "h2.h"
TLorentzVector multiply_by_two(const TLorentzVector v)
{
return 2.0*v;
}
macro.cpp
#include "h1.h"
#include "h2.h"
#include <TLorentzVector.h>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int a = 0;
TLorentzVector v;
v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
return 0;
}
Then you can compile with
g++ -c -g -Wall `root-config --cflags` h1.cpp
g++ -c -g -Wall `root-config --cflags` h2.cpp
g++ -c -g -Wall `root-config --cflags` macro.cpp
and link with
g++ `root-config --glibs` h1.o h2.o macro.o
The executable will be a.out:
$ ./a.out
calling add_one on 0: 1
calling multiply_by_two on 1: 2
You can put these g++ commands in a script or, when you start having several files and directories, you can write your make file (or cmake). For this last step, see for example the tutorial here
http://www-pnp.physics.ox.ac.uk/~brisbane/Teaching/Makefiles/Tutorial_1_Makefiles_and_ROOT.pdf
Note 1: one advantage of using g++ is that you will get clear error messages when something doesn't compile. The error messages from Cint can
be difficult to understand--although this is very much improved in root 6 with Cling.
Note 2: another advantage of using a standard compiler is that you will be able to easily link your main executable against libraries other than root.
This answer is based mostly on the answer by user2148414, but if one follows the answer will notice that there were some issues with the method of linking the source (*.cpp) files. My answer also addresses another important object called a TApplication that will play a crucial role in such applications involving root libraries. The following linking step:
g++ `root-config --glibs` h1.o h2.o macro.o
will likely show a lot of errors complaining about the root objects like TWhatever (in user2148414's answer TLorentzVector will show problems). In the comments to that answer one can find the discussion on including various physics libraries that can solve the problem but without discussing that (and I am not comfortable either :) ) let me write down the command that solves everthing.
This procedure is a one-liner, that is no need to compile individual files, create *.cpp files and *.h files as discussed in that answer then compile and link and create a single executable named "someExecutable" using:
g++ macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable
or better (and one should do it)
g++ -Wall -Wextra -Werror -pedantic -std=c++14 macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable
This will solve my original answer but for completeness I would like to add a few more things.
TApplication
My original motivation was to create an application that talks to "ROOT" but I didn't want to work with the ROOT shell, CINT, ACLiC etc and wanted to work entirely with g++. user2148414's and my answer will solve the part of creating an application but the application will not serve any purpose, it will run, create histograms draw them and do all the stuff but all the canvases will close in the end when the code reaches "return 0;". To keep the canvases open we will need "TApplication". So the consider the main of user2148414's answer, I am going include just two more lines and include two arguments to the main:
macro.cpp
#include "h1.h"
#include "h2.h"
#include <TLorentzVector.h>
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[]) //introduced arguments to main
{
// here I introduce TApplication
TApplication* SomeApp = new TApplication("SomeApp",&argc, argv);
int a = 0;
TLorentzVector v;
v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
//and just before returning 0
SomeApp->Run();
return 0;
}
I am trying to call a C code double_metaphone.c from R in windows. I am familiar with R , but have not tried C yet.
I have compiled the code and created a shared library as follows in windows using Cygwin gcc including the header file double_metaphone.h
gcc -c double_metaphone.c
gcc -shared -o double_metaphone.dll double_metaphone.o
I have used dyn.load to load the dll file as follows
dyn.load("C:/R/double_metaphone.dll")
getLoadedDLLs() lists double_metaphone.dll, however
is.loaded(double_metaphone.dll)
gives the error
Error in is.loaded(double_metaphone.dll) :
object 'double_metaphone.dll' not found
When I try to use .C() or .Call(), I get
Error in .C("double_metaphone") :
C symbol name "double_metaphone" not in load table
I understand this is a problem with C++ code as in Link1, Link, but why can't I access the shared library for calling C code from R? Where am I going wrong?
As per my understanding "is.loaded" checks for the loaded symbols. As per your header, you can try:
is.loaded("DoubleMetaphone")
To call the method. try:
.C("DoubleMetaphone", <your>, <arguments>)
You need compile and link against R for the shared object to be loadable. e.g.
$ gcc -I/YOUR_R_HOME_DIR/include -DNDEBUG -fpic -c double_metaphone.c -o double_metaphone.o
$ gcc -shared -o double_metaphone.dll double_metaphone.o -L/YOUR_R_HOME_DIR/lib -lR
Or simply
$ R CMD SHLIB double_metaphone.c
As Dirk said, R-exts gives you more details.
And you want to consider Rcpp for writing compiled code in R, which benefits you further down the road.
Having trouble using libstatgrab -- I receive the following error at compile time:
"libstatgrabTest.cpp:16: undefined reference to sg_get_process_stats"
I'm guessing it is because I need to include it's .so files at the linking state -- although I'm not sure. As you can see below, I am currently including the statgrab.h header file. I performed configured && make && make install for the library.
If I search for libstatgrab*, I come across the following:
./usr/local/lib/libstatgrab.so.6.2.3
./usr/local/lib/libstatgrab.la
./usr/local/lib/libstatgrab.so.6
./usr/local/lib/libstatgrab.a
./usr/local/lib/libstatgrab.so.6.2.2
./usr/local/lib/libstatgrab.so
./usr/local/lib/pkgconfig/libstatgrab.pc
Another search for statgrab* returns the following (relevant items only):
./usr/local/bin/statgrab
./usr/local/include/statgrab_deprecated.h
./usr/local/include/statgrab.h
At compilation, I run: g++ -g -c libstatgrabTest.cpp
At linking, I run: g++ -L/usr/local/lib libstatgrab.o -o libstatgrabTest
Any idea what I am doing wrong? The code within libstagrabTest.cpp is shown below:
// external libraries
#include <statgrab.h> // libstatgrab (http://www.i-scream.org/libstatgrab/)
// namespace
using namespace std;
int main(void) {
// try to initalize libstatgrab
int * entries;
sg_process_stats * systemStats = sg_get_process_stats(entries);
// return
return 0;
}
g++ -L/usr/local/lib libstatgrab.o -o libstatgrabTest
should be (tested with your code snipper on Ubuntu Natty):
g++ -L/usr/local/lib -o libstatgrabTest -lstatgrab
or, to link statically:
g++ -L/usr/local/lib -o libstatgrabTest /usr/lib/libstatgrab.a
Tested both on my box, with your exact source.
I work in Linux with C++ (Eclipse), and want to use a library.
Eclipse shows me an error:
undefined reference to 'dlopen'
Do you know a solution?
Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*desk)(char*);
char *error;
handle = dlopen ("/lib/CEDD_LIB.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
desk= dlsym(handle, "Apply");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
dlclose(handle);
}
You have to link against libdl, add
-ldl
to your linker options
#Masci is correct, but in case you're using C (and the gcc compiler) take in account that this doesn't work:
gcc -ldl dlopentest.c
But this does:
gcc dlopentest.c -ldl
Took me a bit to figure out...
this doesn't work:
gcc -ldl dlopentest.c
But this does:
gcc dlopentest.c -ldl
That's one annoying "feature" for sure
I was struggling with it when writing heredoc syntax and found some interesting facts. With CC=Clang, this works:
$CC -ldl -x c -o app.exe - << EOF
#include <dlfcn.h>
#include <stdio.h>
int main(void)
{
if(dlopen("libc.so.6", RTLD_LAZY | RTLD_GLOBAL))
printf("libc.so.6 loading succeeded\n");
else
printf("libc.so.6 loading failed\n");
return 0;
}
EOF
./app.exe
as well as all of these:
$CC -ldl -x c -o app.exe - << EOF
$CC -x c -ldl -o app.exe - << EOF
$CC -x c -o app.exe -ldl - << EOF
$CC -x c -o app.exe - -ldl << EOF
However, with CC=gcc, only the last variant works; -ldl after - (the stdin argument symbol).
I was using CMake to compile my project and I've found the same problem.
The solution described here works like a charm, simply add ${CMAKE_DL_LIBS} to the target_link_libraries() call
The topic is quite old, yet I struggled with the same issue today while compiling cegui 0.7.1 (openVibe prerequisite).
What worked for me was to set: LDFLAGS="-Wl,--no-as-needed"
in the Makefile.
I've also tried -ldl for LDFLAGS but to no avail.
you can try to add this
LIBS=-ldl CFLAGS=-fno-strict-aliasing
to the configure options
You needed to do something like this for the makefile:
LDFLAGS='-ldl'
make install
That'll pass the linker flags from make through to the linker. Doesn't matter that the makefile was autogenerated.
I met the same problem even using -ldl.
Besides this option, source files need to be placed before libraries, see undefined reference to `dlopen'.
In order to use dl functions you need to use the -ldl flag for the linker.
how you do it in eclipse ?
Press Project --> Properties --> C/C++ build --> Settings --> GCC C++ Linker --> Libraries -->
in the "Libraries(-l)" box press the "+" sign --> write "dl" (without the quotes)-> press ok --> clean & rebuild your project.
$gcc -o program program.c -l <library_to_resolve_program.c's_unresolved_symbols>
A good description of why the placement of -l dl matters
But there's also a pretty succinct explanation in the docs
From $man gcc
-llibrary
-l library
Search the library named library when linking. (The second
alternative with the library as a separate argument is only for POSIX
compliance and is not recommended.)
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.
Try to rebuild openssl (if you are linking with it) with flag no-threads.
Then try to link like this:
target_link_libraries(${project_name} dl pthread crypt m ${CMAKE_DL_LIBS})
In earlier versions(~2.7) of GNU tool chain, glibc did not have direct interface to link loader(dlopen and dlsym functions), so you had to provide -ldl(libdl) at compile time. You don't have to do that anymore with latest glibc version. Just include <dlcfn.h> and you are good to go.
I'm trying to write a small class library for a C++ course.
I was wondering if it was possible to define a set of classes in my shared object and then using them directly in my main program that demos the library. Are there any tricks involved? I remember reading this long ago (before I started really programming) that C++ classes only worked with MFC .dlls and not plain ones, but that's just the windows side.
C++ classes work fine in .so shared libraries (they also work in non-MFC DLLs on Windows, but that's not really your question). It's actually easier than Windows, because you don't have to explicitly export any symbols from the libraries.
This document will answer most of your questions: http://people.redhat.com/drepper/dsohowto.pdf
The main things to remember are to use the -fPIC option when compiling, and the -shared option when linking. You can find plenty of examples on the net.
My solution/testing
Here's my solution and it does what i expected.
Code
cat.hh :
#include <string>
class Cat
{
std::string _name;
public:
Cat(const std::string & name);
void speak();
};
cat.cpp :
#include <iostream>
#include <string>
#include "cat.hh"
using namespace std;
Cat::Cat(const string & name):_name(name){}
void Cat::speak()
{
cout << "Meow! I'm " << _name << endl;
}
main.cpp :
#include <iostream>
#include <string>
#include "cat.hh"
using std::cout;using std::endl;using std::string;
int main()
{
string name = "Felix";
cout<< "Meet my cat, " << name << "!" <<endl;
Cat kitty(name);
kitty.speak();
return 0;
}
Compilation
You compile the shared lib first:
$ g++ -Wall -g -fPIC -c cat.cpp
$ g++ -shared -Wl,-soname,libcat.so.1 -o libcat.so.1 cat.o
Then compile the main executable or C++ program using the classes in the libraries:
$ g++ -Wall -g -c main.cpp
$ g++ -Wall -Wl,-rpath,. -o main main.o libcat.so.1 # -rpath linker option prevents the need to use LD_LIBRARY_PATH when testing
$ ./main
Meet my cat, Felix!
Meow! I'm Felix
$
As I understand it, this is fine so long as you are linking .so files which were all compiled using the same compiler. Different compilers mangle the symbols in different ways and will fail to link.
That is one of the advantages in using COM on Windows, it defines a standard for putting OOP objects in DLLs. I can compile a DLL using GNU g++ and link it to an EXE compiled with MSVC - or even VB!