dlsym C++ problem. How to dynamically load C++ classes?

Hi, everyone!
I need help very much with C++ on linux. Problem is, that I can dlsym "C" functions, even classes, but I cann't access class methods at all. Either it fails to compile, or I get segmentation fault.

So currently it is like this:

File testVir.h

#ifndef TESTVIR_H
#define TESTVIR_H

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

#endif

File testLib.h

#ifndef TESTLIB_H
#define TESTLIB_H

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

#endif

File testLib.cpp

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

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

static TestLib *cr();
//Define functions with C symbols (create/destroy TestLib instance).
extern "C" TestLib* create()
{
return cr();
}

static TestLib *cr()
{
TestLib *test;
test = new TestLib;
return test;
}

extern "C" void destroy(TestLib* Tl)
{
delete Tl ;
}

That named files above should be compiled as shared(.so) lib.

Now comes main program, that tries to dlsym that and use it:

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

using namespace std;

int main()
{
void *handle;
handle = dlopen("./testLib.so", RTLD_NOW);
if (!handle)
{
cout<< 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 ;
}

Trying to use class's init() function leads to segmentation fault. Any ideas how to make it work? Thanks a lot!
Last edited on
Please use code tags for your code. The tags are in the palette to the right.

You're kind of doing it wrong. And it isn't a "Linux" thing either, you'll get exactly the same problem in Windows with any C++ environment.

The problem you mean is you can get the function name with dlsym(). But you ought to know that where the symbolic name of C functions are known, the mangling scheme for C++ member functions isn't defined. Each vendor can choose different schemes, and they do.

Back to you doing it wrong.

You're defining an object interface. That interface fronts a whole lot of code, and as you know, you really should be using a factory to instantiate your objects. So check this out. It's an interface that's exported from a shared lib to be used by a C++ program.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace kbw
{
    class Shape
    {
    public:
        virtual ~Shape() = 0;
        virtual void Render() = 0;
    };
}

extern "C"
{
    typedef kbw::Shape* kbw_shape_factory_t(const char* name);

    kbw::Shape* create_shape(const char* name);
}

The C++ user of this can write:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <kbw/Shape.hpp>
#include <memory>

int main()
{
    if (void* hModule = dlopen("kbwShapes", RTLD_NOW))
    {
        if (kbw_shape_factory_t* create = (kbw_shape_factory_t*)dlsym(hModule, "create_shape"))
        {
            unique_ptr<kbw::Shape> circle(create("circle"));
            circle.get()->Render();

            unique_ptr<kbw::Shape> square(create("square"));
            square.get()->Render();
        }

        dlclose(hModule);
    }
}


Got it?
Last edited on
Thanks a lot! Unfortunally I'm unable to use "code" etc buttons, since it doesn't work for some reason on my OpenSuSE Leap 42.1 with Firefox(latest version).

I'd like to ask for one more help. Question is, that let's say we have that shape library (.so). And we have executable, that links it over dlsym. Now let's imagine we have one more lib, that the same way dlsyms shape library. I tried using static pointer to avoid recreation of class, but it woks only per one file(either additional lib, or executable), but not on both of them. I tried declarid in Shape lib cpp file static pointer to class declaration and static int counter to count how many created. Generally, if already created, then should return pointer, instead of creating new object. Same story with deletion.

So the question is, if I add some more library that dlsym shape lib and executable that dlsym both libs to get one object for both of them(one copy of Share class), is that possible? And if it is, then how to do that?
As an aside, is this being done for the learning experience, or do you have an actual need to not link in the normal fashion?
Unfortunally I'm unable to use "code" etc buttons, since it doesn't work for some reason on my OpenSuSE Leap 42.1 with Firefox(latest version).

You can always write the tags.
The tag word is within brackets []
The opening tag has word and the closing tag has /word.
The word for code is "code".
I'm learning for myself new methods and will need it for own projects. Reason of not linking it ordinary way is a module system, that will be frequently updated partly and I wanna avoid recompilations etc cauze any single variable change/add. If you meant if that's some part of university task or something, then it's not. It's for personal use and personal project :-)
Topic archived. No new replies allowed.