C++ Shared library: Creation and usage - c++

I am trying to build a shared object to later use a function DoSomethingUseful() from the shared object in other projects.
It uses external libraries as well as a bunch of headers that I am using across multiple projects.
Using CMake, I created a project MySharedLib with a header file called
library.h:
#ifndef MYSHAREDLIB_LIBRARY_H
#define MYSHAREDLIB_LIBRARY_H
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <cstdio>
// own header files
#include <header1.h>
#include <header2.h>
#define PI 3.14159265
//tesseract
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
//openCV
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
//face detection
#include "opencv2/objdetect.hpp"
#include "opencv2/imgproc.hpp"
void DoSomethingUseul(int[] inparray);
#endif
With library.cpp as
#include "library.h"
void DoSomethingUseful(int[] inparray){...}
My CMake file is as such:
cmake_minimum_required(VERSION 3.10)
project(MYSHAREDLIB)
find_package( OpenCV REQUIRED )
set(CMAKE_CXX_STANDARD 11)
set(MY_INCLUDE_DIR ../source/)
set(MY_OPENCV_CASCADES /opencvpath/openCV34/opencv/sources/data/haarcascades/)
include_directories(${MY_INCLUDE_DIR} ${MY_OPENCV_CASCADES} /usr/include)
link_directories(${MY_INCLUDE_DIR})
add_library(MYSHAREDLIB SHARED library.cpp library.h
${MY_INCLUDE_DIR}header1.cpp
${MY_INCLUDE_DIR}header1.h
${MY_INCLUDE_DIR}header2.cpp
${MY_INCLUDE_DIR}header2.h
)
set_target_properties(MYSHAREDLIB PROPERTIES VERSION 3.10)
set_target_properties(MYSHAREDLIB PROPERTIES SOVERSION 1)
target_link_libraries(MYSHAREDLIB lept tesseract ${OpenCV_LIBS})
The *.so file is created sucessfully, i. e. using Clion, no errors are thrown and the file libMySharedLib.so is there.
However, when I want to use the function DoSomethingUseful() in another file DoSomething.cpp:
#include <iostream>
#include "library.h"
using namespace std;
int main()
{
int[2] myarray; myarray[0]=1; myarray[1] =2;
DoSomethingUseful(myarray);
return 0;
}
And
g++ -g -Wall -o DoSomething DoSomething.cpp -I ../source/ -L. libMYSHAREDLIB.so
When I execute
./DoSomething
I get:
./DoSomething: error while loading shared libraries: libMYSHAREDLIB.so: cannot open shared object file: No such file or directory
Before, I compiled without -I ../source/ yielding:
In file included from DoSomething.cpp:8:0:
library.h:19:10: fatal error: header1.h: No such file or directory
#include <header1.h>
I find many threads dealing with this issue in general, and I gathered already a lot of knowledge about shared objects from those issues, also suceeding in getting examples from various tutorials running.
However, I do not suceed with my own project.
This is just one of many questions, but I hope I can get help here and maybe also general hints. Thank you a lot for any help.

Assuming Linux (amend question if wrong). When running an executable, shared libraries are loaded from paths listed in /etc/ld.so.conf only. If you want to load from somewhere else (.) , you have to set the LD_LIBRARY_PATH environment variable, e.g. LD_LIBRARY_PATH=. ./DoSomething

Related

How to link dynamic library "-li2c" with Cmake? (undefined reference to `i2c_smbus_write_byte_data`)

As I'm rather new to Cmake usage, I don't really know how to solve this problem. In my C++ code, I use functions from the Linux i2c library, as follows:
extern "C" {
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
}
#include <sys/ioctl.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
bool cpi2c_writeRegister(uint8_t address, uint8_t subAddress, uint8_t data) {
return i2c_smbus_write_byte_data(address, subAddress, data) == 0;
}
I usually compile with Cmake using CMakeLists, but now it doesn't work since it states: undefined reference to 'i2c_smbus_write_byte_data'. I tried with G++ to link dynamically:
g++ -std=c++11 -Wall -c main.cpp
g++ -std=c++11 -o Main main.o -li2c
This worked well and there are no problems. The problem is I really need to compile with CMakeLists, so do you know a way how to achieve this? Cmake does not find the package by default (since it has no .config-file) and I don't know where the functions from i2c/smbus.h are defined.
Thanks for your help!
Using pkg-config is generally preferred to link libraries that have a .pc file.
But as libi2c does not seem to install a .pc file you can use target_link_libraries() directly by providing the library name. For simplicity and portability use the "Plain library name" (see the target_link_libraries documentation).
target_link_libraries(main i2c)
CMake will take care of expanding the plain library name to -li2c, i2c.lib, or whatever is suited to your build environment and operating system.
Step 1: add
target_link_libraries(${PROJECT_NAME}
i2c
)
To your CMakeList.txt.
Step 2: Declare the headers as "C",
extern "C"
{
#include<linux/i2c-dev.h>
#include <i2c/smbus.h>
}
Because libi2c.so is a dynamic library compiled with GCC.
If you do not declare it explicitly, the g++ will generate different function names in the symbol table thus the ld command cannot find any match in the i2c library.
The answer is, you can use the command target_link_libraries() after creating the executable. You have to provide the name of the object and a path to the .so-file (usually found in /usr/lib). In my case, that would be:
target_link_libraries(main, "/usr/lib/aarch64-linux-gnu/libi2c.so")

emscripten and boost library: how to compile existing project for webassembly?

I have an existing project written on C++ that I would like to compile for webassembly using emscripten. The code calls boost library:
#include <boost/program_options.hpp>
#include <iostream>
#include <string>
#include <exception>
#include <algorithm>
#include <iterator>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/thread/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/assign.hpp>
I have compiled the necessary parts of boost library using emscripten as static libraries and converted them from bc to a-files using emar. Now I'm trying to compile the project feeding the compiler with the precompiled libraries:
(part of Makefile)
C_OPTIONS= -O3 -DNDEBUG -g \
/home/hiisi/workspace/boost_libs/program_options/build/emscripten-1.38.38/release/link-static/threading-multi/libs/cmdline.bc.a \
/home/hiisi/workspace/boost_libs/program_options/build/emscripten-1.38.38/release/link-static/threading-multi/libs/config_file.bc.a \
/home/hiisi/workspace/boost_libs/program_options/build/emscripten-1.38.38/release/link-static/threading-multi/libs/convert.bc.a \
/home/hiisi/workspace/boost_libs/program_options/build/emscripten-1.38.38/release/link-static/threading-multi/libs/libboost_program_options.bc.a \
However make still complains on the very first occurrence of boost in the code:
main.cpp:1:10: fatal error: 'boost/program_options.hpp' file not found
#include <boost/program_options.hpp>
^~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
shared:ERROR: compiler frontend failed to generate LLVM bitcode, halting
The question may sound little bit naive, but how do I correctly do this? The project compiles perfectly fine with g++, but not em++
All I had to do is to make sure that boost lib presents in emscripten include directory. In my case that was emsdk/fastcomp/emscripten/system/include/ I made a symlink to system' boost library there and everything worked like a charm.
You have to add the include directories to use boost.
That would be an argument that look like this:
... -I/home/hiisi/workspace/boost_libs/include ...

C++ Compiles in Windows, multiple definition error in Linux

let me start by saying that I am not the best C++ and I know very little in ways of Linux. For a class project we had to implement a heap so I coded everything on my Windows PC assuming I could just upload the files to the Linux repository the school has. [Perhaps this is where I went wrong and this cannot be done this simply.] My codes compiles and clears all test cases provided on my Windows pc. When I upload the files to Linux, I created a makefile and when I use the make command I get back a laundry list of multiple definition errors. One error per function that I am using. I have done some searching and I am more confused then when I started.
My files are: main.cpp, main.h, heap.cpp, heap.h, util.cpp, and util.h.
I think the issue is with my include statements but I am not 100% sure.
Here is an example of the files.
main.cpp
#include <iostream> //needed to use basic inputs/outputs
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "util.cpp"
#include "heap.cpp"
#include <fstream>
using namespace std;
main.h is blank.
heap.cpp
#include <iostream> //needed to use basic inputs/outputs
#include <stdio.h>
#include <stdlib.h>
#include "heap.h"
#include <cmath>
#include <math.h>
using namespace std;
//expanded functions found in the heap.h file
heap.h
//2 structs
//9 functions
util.cpp
#include <iostream> //needed to use basic inputs/outputs
#include <stdio.h>
#include <stdlib.h>
#include "util.h"
using namespace std;
//expanded functions found in util.h
util.h
//1 function
Between heap.h and util.h I have 10 function and upon running the make command I get a warning about all ten:
multiple definition of 'FUNCTIONNAME'
main.o:main.cpp:(.text+0x1b7): first defined here
I am assuming the 0x1b7 is a memory location because they are each different.
Any help would be greatly appreciated.
You haven't shown the Makefile, but most likely, it includes this or a similar rule
program: main.o heap.o util.o
$(CXX) $(CXXFLAGS) -o program main.o heap.o util.o
What happens now, the compiler builds the three object files main.o, heap.o and util.o. Next the object files are linked together to build program.
The linker sees definitions of the various functions defined in both main.o and heap.o, or main.o and util.o respectively. This is why it complains about "multiple definition of 'FUNCTIONNAME'"
Why are these functions defined more than once?
When you include a file into another source, it is as if you copy the contents at the location of the #include. This means a function defined in heap.cpp:
void create_heap(int size)
{
// create a heap ...
}
is copied verbatim into main.cpp where the line
#include "heap.cpp"
is.
Because heap.cpp has the definition of create_heap() and main.cpp #includes the contents of heap.cpp, both contain their own copy of create_heap(). Now you compile both heap.o and main.o, and link them together. Each object file has a copy of create_heap() and this is where the linker is confused and complains
multiple definition of 'create_heap'
main.o:main.cpp:(.text+0x1b7): first defined here
To fix this, simply replace the lines including the cpp sources, e.g.
#include "util.cpp"
#include "heap.cpp"
with their respective header files
#include "util.h"
#include "heap.h"
Only keep the function definitions relevant to main.cpp, nothing else. Now main.cpp has no function definitions belonging to util.cpp or heap.cpp, and the linker errors are gone.
Presumably, this worked on Windows, because only main.cpp was included in the project file, and so only one definition (from main.o) was in the resulting executable.
If you had included all sources as in the Linux Makefile, the error could be seen in Windows as well.

Compile error : fatal error: 'boost/numeric/ublas/matrix.hpp' file not found

These are the header files and libraries
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <numeric>
#include <strings.h>
#include <assert.h>
#include <dirent.h>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/adapted/c_array.hpp>
#include "mail.h"
I am trying to compile this c++ file I got using
g++ -O3 -DNDEBUG -o evaluate_object evaluate_object.cpp
The compile output
evaluate_object.cpp:13:10: fatal error: 'boost/numeric/ublas/matrix.hpp' file
not found
#include <boost/numeric/ublas/matrix.hpp>
^
1 error generated.
Ps: I run on macos sierra 10.12
I have tried install boost by these ways:
sudo port install boost
brew install boost
sudo port install boost +universal
But I still got the same problem.
I would be happy to get out of this noob zone.
I am a macos newbie too.
It seems that your "boost" includes directory is not present within environment defined include directories. You might want to specify one by passing "-I" argument to g++ command, i.e.
g++ -O3 -DNDEBUG -I/usr/local/Cellar/blahblah -o evaluate_object evaluate_object.cpp
Also your code is incomplete and perhaps if you actually call some of the boost functions you might need to add some objects for linking and then you will face "undefined reference to" error. To overcome such you need to specify "-L" flag for your g++ command.

New to OpenGL - how to compile?

I have a file with the following imports:
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/norm.hpp>
using namespace glm;
// Include AntTweakBar
#include <AntTweakBar.h>
#include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>
#include <common/objloader.hpp>
#include <common/vboindexer.hpp>
#include <common/quaternion_utils.hpp> // See quaternion_utils.cpp for RotationBetweenVectors, LookAt and RotateTowards
However, when I try to compile it with
g++ -lglut -lGLU -lGL rotatetest.cpp -o hello.o
I get the following errors:
rotatetest.cpp:7:23: error: GLUT/glew.h: No such file or directory
rotatetest.cpp:10:19: error: glfw3.h: No such file or directory
rotatetest.cpp:14:23: error: glm/glm.hpp: No such file or directory
rotatetest.cpp:15:40: error: glm/gtc/matrix_transform.hpp: No such file or directory
rotatetest.cpp:16:34: error: glm/gtc/quaternion.hpp: No such file or directory
rotatetest.cpp:17:34: error: glm/gtx/quaternion.hpp: No such file or directory
rotatetest.cpp:18:36: error: glm/gtx/euler_angles.hpp: No such file or directory
rotatetest.cpp:19:28: error: glm/gtx/norm.hpp: No such file or directory
rotatetest.cpp:23:25: error: AntTweakBar.h: No such file or directory
I know this code works because a) it's from a tutorial and b) I can successfully run it when it is part of an XCode project, just not as a standalone file.
I am on Mac OS X 10.8.5. Can anyone suggest to me how I can compile this?
The include<> directives in your file ask for OpenGL-related headers in your system include directory. g++ on the command line may be using a different system include directory than XCode is.
Make sure that the extra OpenGL headers (GLFW, GLM, GLUT) are placed in your g++ installation as well.
You probably will also have to do this for the static libraries as well.