I am trying to use the prebuilt tensorflow c-api with a cpp-wrapper in my package. Unfortunately I am getting a segfault error. After searching I found out that there is a Git Issue about it: Linking to both tensorflow and protobuf causes segmentation fault during static initializers.
So I could resolve the Issues by doing:
The workarounds sound like (1) only load the second copy of protobuf in a .so that does not use TensorFlow, and you can use both that .so and TensorFlow's .so from your main program, (2) instead of linking normally, dlopen() TensorFlow with RTLD_DEEPBIND set so TensorFlow prefers its own symbols.
I want to try to load the library using dlopen(), unfortunately I have never used it and I cannot find a good example of its use. How would I use it in my case and where?
My initial understanding:
Load it into the header of my cpp-wrapper since they use the tensorflow functions/header?
But than do I really need to change every single function of the cpp-wrapper header, and put a reference to the loaded handler?
A little dlopen example:
Some lib written in C, we call it foobar.so
#include <stdio.h>
void foo() { printf("foo\n"); }
void bar() { printf("bar\n"); }
gcc -o foobar.so foobar.c -shared -fPIC
A (foobar) wrapper in C++
#include <dlfcn.h>
struct FooBar {
typedef void (*foo_handle)(); //same signature as in the lib
typedef void (*bar_handle)(); //same signature as in the lib
foo_handle foo;
bar_handle bar;
void *foobar_lib;
FooBar() {
//probably best not in the constructor, but we're lazy (for now)
//and of course no error checking (so don't)
foobar_lib = dlopen("./foobar.so", RTLD_LAZY | RTLD_DEEPBIND);
foo = reinterpret_cast<foo_handle>(dlsym(foobar_lib, "foo"));
bar = reinterpret_cast<bar_handle>(dlsym(foobar_lib, "bar"));
}
~FooBar() {
dlclose(foobar_lib);
}
};
int main()
{
FooBar foobar;
foobar.foo();
foobar.bar();
return 0;
}
or
#include <dlfcn.h>
typedef void (*foo_handle)(); //same signature as in the lib
typedef void (*bar_handle)(); //same signature as in the lib
foo_handle foo;
bar_handle bar;
void *foobar_lib;
int main()
{
foobar_lib = dlopen("./foobar.so", RTLD_LAZY | RTLD_DEEPBIND);
foo = reinterpret_cast<foo_handle>(dlsym(foobar_lib, "foo"));
bar = reinterpret_cast<bar_handle>(dlsym(foobar_lib, "bar"));
foo();
bar();
dlclose(foobar_lib);
return 0;
}
g++ -ldl -o foobar_test foobar_test.cpp
For each and every symbol you use from the original lib, you will have to call dlsym to obtain its address.
So yes, it is a tedious work, since you're implementing a wrapper to provide the full functionality of the underlying library.
For example, opengl developers knows very well what that means. Luckily, over the years there are now many tools available, which helps to load the myriads of symbols in runtime with no/less effort. Maybe there is something similar to tensorflow.
Related
EDIT: Nearly got the answer, I just dont completely understand it, see last paragraph.
I try to build a shared lua library and use it within a larger project. When calling the script which loads the shared library from shell everything works. However, when I wrap the script within another shell, I get a runtime error when loading the library. Dependent on the script it is just any call to a lua function from c (i.e. lua_pushnumber). Here is a minimal example.
totestlib.cpp:
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
int init(lua_State *L) {
lua_toboolean(L, -1);
return 0;
}
static const struct luaL_Reg testlib[] = {
{"init", init},
{NULL, NULL}
};
extern "C"
int luaopen_libtotestlib(lua_State *L) {
luaL_newlib(L, testlib);
return 1;
}
Compiled with: g++ -shared -fPIC -I./lua-5.4.4/src -L./lua-5.4.4/src totestlib.cpp -o libtotestlib.so
testlib.lua (testing shared library):
testlib.lua
print("start")
testlib = require("libtotestlib")
print("done")
testlib.init(true)
print("called")
Calling the lua script using ./lua-5.4.4/src/lua testlib.lua works. Everything is printed. Wrapping script in the following c++ code does not work:
call_testlib.cpp
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <unistd.h>
static lua_State *L;
int main(int argc, char *argv[]) {
L = luaL_newstate();
luaL_openlibs(L);
int tmp = luaL_loadfile(L, "testlib.lua");
if(tmp != 0) {
return 1;
}
tmp = lua_pcall(L, 0, 0, 0);
if(tmp != 0) {
printf("error pcall\n");
return 1;
}
}
Compiled with g++ call_testlib.cpp -o ./call_testlib -I./lua-5.4.4/src -L./lua-5.4.4/src -llua it prints "error pcall". If I print the error message on the lua stack, I get:
string error loading module 'libtotestlib' from file './libtotestlib.so':
./libtotestlib.so: undefined symbol: luaL_checkversion_
In this case the undefined symbol is luaL_checkversion_ (which I dont call myself), but with other scripts it is usually the first lua_... function that I call.
I have tried several things to fix this. For example, linking -llua when compiling the shared library, but this does not work (and should not be the problem as calling the script itself works). I also tried to load preload the library from c++ (as done in this question) instead of from lua, but I guess it does not really make a difference and I am getting the same error. I also uninstalled all lua versions from my path to make sure I always use the same version.
What is the difference between calling the script directly from shell and calling it inside a c function? Am I doing something wrong?
EDIT: Nearly got the answer. When using MYCFLAGS= -fPIC when compiling lua I can link lua to the shared library. At least this one works, but does not seem like a good solution to me and does not really answer my question: Why can lua itself (from shell) somehow add these symbols to the library while the wrapped c version can not? Additionally, my program has lua once linked in the shared library and once in the compiled C++ project (not optimal imo).
UPD (SOLVED): This issue has been solved by this - In short, the case CMAKE will produce visiable UNIQUE objects, and either -fvisibility=hidden (then add attribute visibility=default manually) or --no-gnu-unique can avoid the problem.
I found this when importing a large project into myselfs, and the following codes should be a minimal demo to illustrate it:
/* ---- header.h ---- */
struct A {
typedef (void (*func_t)();
static void empty() {}
static constexpr func_t funcs[1] = {empty};
const func_t *func_list;
A() { func_list = funcs; }
};
struct B {
B();
};
struct X {
A a;
B b;
};
/* ----- header.cpp ----- */
#include "header.h"
B::B() {}
/* ----- main.cpp ----- */
#include "header.h"
extern "C" {
void test() {
auto x = new X;
delete x;
// print(version_nubmer);
}
}
The library is built from CMake
add_library(main SHARED main.cpp header.cpp)
target_compile_options(main PRIVATE -fPIC)
Then I use a program that sequentially calls dlopen(); dlsym(test)(); dlclose(); dlopen(); dlsym(test)(); on this library (with RTLD_LAZY | RTLZ_LOCAL), where before the second dlopen(),
I change the version number to a different value, expecting it print the updated one. But, it doesn't. I still see it give the old value, which means dlclose() does not really detach the lib.
If I set CMAKE_INTERPROCEDURAL_OPTIMIZATION to ON, or manually build it from command line (e.g., g++ -o libmain.so -fPIC -shared main.cpp header.cpp) the observation disapears. Can anyone tell the difference here?
UPD: Between the dlclose() and second dlopen(), we insert something to block the program like scanf() or getchar(), and continue the program only after we rebuilt the lib. This will ensure the reproduction to the three cases (CMAKE, CMAKE+lto, cmd).
You can not rely on dlclose() to unload any library.
Per POSIX (bolding mine):
The dlclose() function shall inform the system that the symbol table handle specified by handle is no longer needed by the application.
An application writer may use dlclose() to make a statement of intent on the part of the process, but this statement does not create any requirement upon the implementation. ...
Assuming you're running on Linux:
A successful return from dlclose() does not guarantee that the
symbols associated with handle are removed from the caller's
address space.
I have a shared library that I would like to make executable, similar to libc. When the library executes, I would like it to dump a list of the names of classes that are registered with a particular abstract factory (this is C++). I use the standard technique of registering classes with the factory through the initialization/construction of global variables.
There are several tutorials on how to make shared libraries executable (here and here, for example). It's relatively straight forward. However, when I try it out, I find that the entry point is executed before any constructors of globals are called. In my case, this means that no classes have registered with my factory, so I have no information to print out.
I would like to either execute the entry point after the constructors have been called, or learn how to trigger construction myself from my entry-point function. Is this possible? Does anyone know how to go about doing this? Perhaps there is an internal libc function that I can extern and call?
I believe that I have come across a workable solution. It is based upon techniques for creating -nostdlib executables (such as OS kernels). However, our shared library still links the standard libraries in this case. I found this RaspberryPi forum thread especially useful.
The solution is to manually execute the function pointers stored in the shared library's embedded init_array. The trick is to use a linker script to define pointers for accessing this array. We then extern these pointers in the program code. We can repeat the process for executing destructors as well.
In test.cpp, we have the following:
#include <cstdio>
#include <unistd.h>
class Test
{
public:
Test() { printf("Hello world!\n"); }
~Test() { printf("Goodbye world!\n"); }
};
Test myGlobal; // a global class instance
extern "C"
{
// ensures linker generates executable .so (assuming x86_64)
extern const char test_interp[] __attribute__((section(".interp"))) =
"/lib64/ld-linux-x86-64.so.2";
// function walks the init_array and executes constructors
void manual_init(void)
{
typedef void (*constructor_t)(void);
// _manual_init_array_start and _manual_init_array_end
// are created by linker script.
extern constructor_t _manual_init_array_start[];
extern constructor_t _manual_init_array_end[];
constructor_t *fn = _manual_init_array_start;
while(fn < _manual_init_array_end)
{
(*fn++)();
}
}
// function walks the fini_array and executes destructors
void manual_fini(void)
{
typedef void (*destructor_t)(void);
// _manual_init_array_start and _manual_init_array_end
// are created by linker script.
extern destructor_t _manual_fini_array_start[];
extern destructor_t _manual_fini_array_end[];
destructor_t *fn = _manual_fini_array_start;
while(fn < _manual_fini_array_end)
{
(*fn++)();
}
}
// entry point for libtest.so when it is executed
void lib_entry(void)
{
manual_init(); // call ctors
printf("Entry point of the library!\n");
manual_fini(); // call dtors
_exit(0);
}
We need to manually define the _manual* pointers through a linker script. We must use the INSERT keyword so that don't entirely replace ld's default linker script. In a file test.ld, we have:
SECTIONS
{
.init_array : ALIGN(4)
{
_manual_init_array_start = .;
*(.init_array)
*(SORT_BY_INIT_PRIORITY(.init_array.*))
_manual_init_array_end = .;
}
}
INSERT AFTER .init; /* use INSERT so we don't override default linker script */
SECTIONS
{
.fini_array : ALIGN(4)
{
_manual_fini_array_start = .;
*(.fini_array)
*(SORT_BY_INIT_PRIORITY(.fini_array.*))
_manual_fini_array_end = .;
}
}
INSERT AFTER .fini; /* use INSERT so we don't override default linker script */
We must provide two parameters to the linker: (1) our linker script and (2) the entry point to our library. To compile, we do the following:
g++ test.cpp -fPIC -Wl,-T,test.ld -Wl,-e,lib_entry -shared -o libtest.so
We get the following output when libtest.so is executed at the commandline:
$ ./libtest.so
Hello world!
Entry point of the library!
Goodbye world!
I've also tried defining globals in .cpp files other than test.cpp that are also compiled into the shared library. The ctor calls for these globals are included in init_array, so they are called by manual_init(). The library works "like normal" when it is loaded as a regular shared library.
I want to call a function from C++ library on linux. I have a shared object of that library.
I want to call method getAge() that return an int from ydmg library.
Following is the code that I have written:
testydmg.cpp
#include "ydmg/bd.h"
#include "yut/hash.h"
#include "dlfcn.h"
extern "C" int getAge();
class testydmg{
public:
testydmg::testydmg(const yutHash& user){
}
testydmg::testydmg(){
}
testydmg::~testydmg(){
}
int testydmg::getFunction(){
void *handle;
int (*voidfnc)();
handle = dlopen("ydmg.so",RTLD_LAZY);
if(handle == NULL){
printf("error in opening ydmg lib");
} else {
voidfnc = (int (*)())dlsym(handle, "getAge");
(*voidfnc)();
printf("class loaded");
}
ydmgBd obj;
obj.getAge();
printf("Inside getFunction()...");
dlclose(handle);
}
};
I compile and link the code as below:
gcc -fPIC -shared -l stdc++ -I/home/y/libexec64/jdk1.6.0/include -I/home/y/libexec64/jdk1.6.0/include/linux -I/home/y/include testydmg.cpp -o libTestYdmg.so libydmg.so
Then I check for the method in the new shared object i.e. libTestYdmg.so
nm -C libTestYdmg.so | egrep getAge
I get nothing by running the above command.
Does it mean that it did not get the method getAge() from the library.
Could you please correct where I am going wrong ?
You want to use ydmgDB::getAge() but you are asking to the library for getAge(). This is not correct, just simply create a ydmgDBobject and invoke it's method getAge() without loading the library that is linked with your compile command line.
You don't need to dlopen the library.
Besides, getAge is not really included in libTestYdmg.so. You must look for it in libydmg.so using:
nm -C libydmg.so | grep getAge
If you're interested in actually using dlopen in C++ code, take a look at the
C++ dlopen mini HOWTO, which includes example code and some possibly important
warnings.
This is a follow-up to Dynamic Shared Library compilation with g++.
I'm trying to create a shared class library in C++ on Linux. I'm able to get the library to compile, and I can call some of the (non-class) functions using the tutorials that I found here and here. My problems start when I try to use the classes that are defined in the library. The second tutorial that I linked to shows how to load the symbols for creating objects of the classes defined in the library, but stops short of using those objects to get any work done.
Does anyone know of a more complete tutorial for creating shared C++ class libraries that also shows how to use those classes in a separate executable? A very simple tutorial that shows object creation, use (simple getters and setters would be fine), and deletion would be fantastic. A link or a reference to some open source code that illustrates the use of a shared class library would be equally good.
Although the answers from codelogic and nimrodm do work, I just wanted to add that I picked up a copy of Beginning Linux Programming since asking this question, and its first chapter has example C code and good explanations for creating and using both static and shared libraries. These examples are available through Google Book Search in an older edition of that book.
myclass.h
#ifndef __MYCLASS_H__
#define __MYCLASS_H__
class MyClass
{
public:
MyClass();
/* use virtual otherwise linker will try to perform static linkage */
virtual void DoSomething();
private:
int x;
};
#endif
myclass.cc
#include "myclass.h"
#include <iostream>
using namespace std;
extern "C" MyClass* create_object()
{
return new MyClass;
}
extern "C" void destroy_object( MyClass* object )
{
delete object;
}
MyClass::MyClass()
{
x = 20;
}
void MyClass::DoSomething()
{
cout<<x<<endl;
}
class_user.cc
#include <dlfcn.h>
#include <iostream>
#include "myclass.h"
using namespace std;
int main(int argc, char **argv)
{
/* on Linux, use "./myclass.so" */
void* handle = dlopen("myclass.so", RTLD_LAZY);
MyClass* (*create)();
void (*destroy)(MyClass*);
create = (MyClass* (*)())dlsym(handle, "create_object");
destroy = (void (*)(MyClass*))dlsym(handle, "destroy_object");
MyClass* myClass = (MyClass*)create();
myClass->DoSomething();
destroy( myClass );
}
On Mac OS X, compile with:
g++ -dynamiclib -flat_namespace myclass.cc -o myclass.so
g++ class_user.cc -o class_user
On Linux, compile with:
g++ -fPIC -shared myclass.cc -o myclass.so
g++ class_user.cc -ldl -o class_user
If this were for a plugin system, you would use MyClass as a base class and define all the required functions virtual. The plugin author would then derive from MyClass, override the virtuals and implement create_object and destroy_object. Your main application would not need to be changed in any way.
The following shows an example of a shared class library shared.[h,cpp] and a main.cpp module using the library. It's a very simple example and the makefile could be made much better. But it works and may help you:
shared.h defines the class:
class myclass {
int myx;
public:
myclass() { myx=0; }
void setx(int newx);
int getx();
};
shared.cpp defines the getx/setx functions:
#include "shared.h"
void myclass::setx(int newx) { myx = newx; }
int myclass::getx() { return myx; }
main.cpp uses the class,
#include <iostream>
#include "shared.h"
using namespace std;
int main(int argc, char *argv[])
{
myclass m;
cout << m.getx() << endl;
m.setx(10);
cout << m.getx() << endl;
}
and the makefile that generates libshared.so and links main with the shared library:
main: libshared.so main.o
$(CXX) -o main main.o -L. -lshared
libshared.so: shared.cpp
$(CXX) -fPIC -c shared.cpp -o shared.o
$(CXX) -shared -Wl,-soname,libshared.so -o libshared.so shared.o
clean:
$rm *.o *.so
To actual run 'main' and link with libshared.so you will probably need to specify the load path (or put it in /usr/local/lib or similar).
The following specifies the current directory as the search path for libraries and runs main (bash syntax):
export LD_LIBRARY_PATH=.
./main
To see that the program is linked with libshared.so you can try ldd:
LD_LIBRARY_PATH=. ldd main
Prints on my machine:
~/prj/test/shared$ LD_LIBRARY_PATH=. ldd main
linux-gate.so.1 => (0xb7f88000)
libshared.so => ./libshared.so (0xb7f85000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e74000)
libm.so.6 => /lib/libm.so.6 (0xb7e4e000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7e41000)
libc.so.6 => /lib/libc.so.6 (0xb7cfa000)
/lib/ld-linux.so.2 (0xb7f89000)
On top of previous answers, I'd like to raise awareness about the fact that you should use the RAII (Resource Acquisition Is Initialisation) idiom to be safe about handler destruction.
Here is a complete working example:
Interface declaration: Interface.hpp:
class Base {
public:
virtual ~Base() {}
virtual void foo() const = 0;
};
using Base_creator_t = Base *(*)();
Shared library content:
#include "Interface.hpp"
class Derived: public Base {
public:
void foo() const override {}
};
extern "C" {
Base * create() {
return new Derived;
}
}
Dynamic shared library handler: Derived_factory.hpp:
#include "Interface.hpp"
#include <dlfcn.h>
class Derived_factory {
public:
Derived_factory() {
handler = dlopen("libderived.so", RTLD_NOW);
if (! handler) {
throw std::runtime_error(dlerror());
}
Reset_dlerror();
creator = reinterpret_cast<Base_creator_t>(dlsym(handler, "create"));
Check_dlerror();
}
std::unique_ptr<Base> create() const {
return std::unique_ptr<Base>(creator());
}
~Derived_factory() {
if (handler) {
dlclose(handler);
}
}
private:
void * handler = nullptr;
Base_creator_t creator = nullptr;
static void Reset_dlerror() {
dlerror();
}
static void Check_dlerror() {
const char * dlsym_error = dlerror();
if (dlsym_error) {
throw std::runtime_error(dlsym_error);
}
}
};
Client code:
#include "Derived_factory.hpp"
{
Derived_factory factory;
std::unique_ptr<Base> base = factory.create();
base->foo();
}
Note:
I put everything in header files for conciseness. In real life you should of course split your code between .hpp and .cpp files.
To simplify, I ignored the case where you want to handle a new/delete overload.
Two clear articles to get more details:
C++ dlopen mini how-to
C++ Dynamic Loading of Shared Objects at Runtime
Basically, you should include the class' header file in the code where you want to use the class in the shared library. Then, when you link, use the '-l' flag to link your code with the shared library. Of course, this requires the .so to be where the OS can find it. See 3.5. Installing and Using a Shared Library
Using dlsym is for when you don't know at compile time which library you want to use. That doesn't sound like it's the case here. Maybe the confusion is that Windows calls the dynamically loaded libraries whether you do the linking at compile or run-time (with analogous methods)? If so, then you can think of dlsym as the equivalent of LoadLibrary.
If you really do need to dynamically load the libraries (i.e., they're plug-ins), then this FAQ should help.