I have my_program
which loads some shared libraries. Basicaly user can create one project and then that project can be executed with my_program
. I want to load class from shared library. I've found this example: C++ Dynamic Shared Library on Linux
This example is great, but I have a problem. I don't have header file. So, is there any possible way to load class for which I don't have header file? I suppose there isn't. If I am not mistaken I don't think that there is a way to load header file dynamically?
If user write class Child : public Parent
then in my main program I must replace MyClass
(from that example that I provided) with Child. I know which methods are in Child class, becase I provide BaseParent
class with pure virtual methods. So I would include BaseParent
in my main program. But still I would need to know class name of this project.
What if I say that project class name must be always MY_PROJECT? Would that help?
Then I would know that I must replace MyClass
(from example above) with MY_PROJECT
but wouldn't that trigger an error because main program wouldn't know nothing about class MY_PROJECT
?
I'm open for any suggestions because I am literally stuck.
EDIT: If I have this class which is in main program:
class BaseParent
{
public:
virtual bool init(const TestCase&);
virtual void run();
virtual bool done();
}
Next two classes are writen by user who creates project
class Parent : public BaseParent
{
public:
bool init(const TestCase &test)
{
//implementation of this method
}
void run()
{
execute(.....);
}
bool done()
{
//implementation of this method
}
//he must also define this method which is in child class
virtual void execute(...);
};
And the other class
class Child : public Parent
{
public:
void execute(...)
{
//implementation of this method
}
};
extern "C" Child* create_object()
{
return new Child;
}
extern "C" void destroy_object( Child* object )
{
delete object;
}
So, I can include only BaseParent
in my main program. If Child class return pointer to BaseParent
then I can call methods like init, done, and run like this bellow? Even that BaseParent
is not aware of execute which is called in run?
void *handle = dlopen(shared_lib, RTLD_LAZY);
if (handle)
{
BaseParent* (*create)();
void (*destroy)(BaseParent*);
create = (BaseParent* (*)())dlsym(handle, "create_object");
destroy = (void (*)(BaseParent*))dlsym(handle, "destroy_object");
BaseParent* myClass = (BaseParent*)create();
myClass->init(test); //wouldn this trigger an error because it's not implemented in BaseParent but in Child?
}
Edit 2:
BaseParent* (*create)();
void (*destroy)(BaseParent*);
//other code.... buff is path to libProject.so
void *handle = dlopen(buff, RTLD_LAZY);
if (handle)
{
create = (BaseParent* (*)())dlsym(handle, "create_object");
destroy = (void(*)(BaseParent*))dlsym(handle, "destroy_object");
BaseParent *a = (BaseParent*)create();
a->run();
}else
{
LOG(ERROR) << "Error in opening lib " << buff;
return;
}
Problem is that linker (on OS X) gives me an error:
Undefined symbols for architecture x86_64:
"BaseParent::run()", referenced from:
vtable for BaseParent in BaseParent
"BaseParent::init(TestCase&)", referenced from:
vtable for BaseParent in BaseParent
ld: symbol(s) not found for architecture x86_64
But on Ubuntu 12.04 I get this:
(gdb)
99 AbsAlgorithm *a = (AbsAlgorithm*)create();
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
So, that run and init method are virtual as you can see above. Any advice?