2

I try to load libraries dynamically in c++. I follow this tutorial. My folder structure is like this :

├── main.cpp
├── testLib.cpp
├── testLib.h
├── testLib.so
└── testVir.h

main.cpp

#include<iostream>
#include<dlfcn.h>
#include<stdio.h>
#include "testVir.h"

using namespace std;

int main()
{
    void *handle;
    handle = dlopen("./testLib.so", RTLD_NOW);
    if (!handle)
    {
           printf("The error is %s", dlerror());
    }

    typedef TestVir* create_t();
    typedef void destroy_t(TestVir*);

    create_t* creat=(create_t*)dlsym(handle,"create");
    destroy_t* destroy=(destroy_t*)dlsym(handle,"destroy");
    if (!creat)
    {
           cout<<"The error is %s"<<dlerror();
    }
    if (!destroy)
    {
           cout<<"The error is %s"<<dlerror();
    }
    TestVir* tst = creat();
    tst->init();
    destroy(tst);
    return 0 ;
}

testLib.cpp

#include <iostream>
#include "testVir.h"
#include "testLib.h"

using namespace std;
void TestLib::init()
{
   cout<<"TestLib::init: Hello World!! "<<endl ;
}

//Define functions with C symbols (create/destroy TestLib instance).
extern "C" TestLib* create()
{
    return new TestLib;
}
extern "C" void destroy(TestLib* Tl)
{
   delete Tl ;
}

testLib.h

#ifndef TESTLIB_H
#define TESTLIB_H

class TestLib
{
 public:
     void init();
};

#endif

testVir.h

#ifndef TESTVIR_H
#define TESTVIR_H

class TestVir
{
public:
  virtual void init()=0;
};

#endif

I get my testLib.so using this command g++ -shared -fPIC testLib.cpp -o testLib.so , this works fine, but when i try to compile my main with g++ -ldl main.cpp -o test i get this errors :

/tmp/ccFoBr2X.o: In function `main':
main.cpp:(.text+0x14): undefined reference to `dlopen'
main.cpp:(.text+0x24): undefined reference to `dlerror'
main.cpp:(.text+0x47): undefined reference to `dlsym'
main.cpp:(.text+0x5c): undefined reference to `dlsym'
main.cpp:(.text+0x6c): undefined reference to `dlerror'
main.cpp:(.text+0x95): undefined reference to `dlerror'
collect2: error: ld returned 1 exit status

G++ version ( from g++ --version ) :
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4

I don't know what is going one, I would need some resources in learning how this works.

EDIT 1 I solved the problem by using this command to compile my main. g++ main.cpp -ldl -o test. Found this fix in this answer .

But now when i try to run ./test i get Segmentation fault. And it seems to be at this line tst->init(); but the pointer looks valid.

EDIT 2 Following this tutorial i get the same error, Segmentation fault.

If you have good tutorials or documentations it would really help.

Community
  • 1
  • 1
Matei
  • 1,783
  • 1
  • 14
  • 17
  • this works: static_cast(tst)->init() – Patrick Trentin Mar 16 '16 at 11:39
  • 2
    You need to move your linker flags to the end of the command: `g++ main.cpp -o test -ldl` – Galik Mar 16 '16 at 11:50
  • Also according to the manual you should cast the symbol pointer to (void**) when assigning from `dlsym()` because direct casting can lose bits on some systems. See example in the mnual: http://linux.die.net/man/3/dlopen They do `*(void**) (&create) = dlsym(handle, "create");` – Galik Mar 16 '16 at 12:00

1 Answers1

3

This is not related to the dlopen part. Your class TestLib is missing the inheritance from TestVir:

class TestLib : public TestVir

You should also fix your create/destroy signatures to be of identical type. Since you want to hide the TestLib class, you should return and take TestVir*.

extern "C" TestVir* create()
{
    return new TestLib();
}
extern "C" void destroy(TestVir* Tl)
{
   delete Tl ;
}

Also put the function types into a header, or you will just shoot yourself in the foot some time later. For that to work you also must have virtual destructor in the base class.

class TestVir
{
public:
    virtual void init()=0;
    virtual ~TestVir() = default; // note: C++11
};

By the way: Your error handling is missing flushes, and you should not go on in case of error.

Zulan
  • 21,896
  • 6
  • 49
  • 109
  • Do you have any documentation that i could read, or tutorials about this subject ?Thanks for help . – Matei Mar 16 '16 at 12:24
  • @Matei I suppose the book Effective C++, item 7 would be a good starting point. Depending on your C++ knowledge a basic book such as "The C++ Programming Language, 4th Edition" might be helpful for you. The combination with dynamic library loading and C++ is neither very common, nor particularly elegant (unfortunately), but if you are more proficient with the language itself and [writing libraries](https://www.youtube.com/watch?v=hcHUZE6buzE), the `dlopen` part is not that complicated. – Zulan Mar 16 '16 at 12:36
  • @Matei there is also [Boost.DLL](http://www.boost.org/doc/libs/master/doc/html/boost_dll.html), but I have no personal experience with that. – Zulan Mar 16 '16 at 12:38