我有my_program加载了一些共享库。基本上,用户可以创建一个项目,然后可以使用my_program执行该项目。我想从共享库加载类。我找到了以下示例:C++ Dynamic Shared Library on Linux

这个例子很棒,但是我有一个问题。我没有头文件。
那么,有没有什么方法可以加载我没有头文件的类?我想没有。
如果我没记错的话,我不认为有一种动态加载头文件的方法吗?

如果用户写class Child : public Parent,那么在我的主程序中,我必须用Child替换MyClass(根据我提供的示例)。我知道子类中有哪些方法,例如我为BaseParent类提供了纯虚拟方法。因此,我将在主程序中包含BaseParent。但是我仍然需要知道这个项目的类名。

如果我说项目类名称必须始终为MY_PROJECT怎么办?有帮助吗?
然后我知道我必须用MyClass替换MY_PROJECT(来自上面的示例),但是那不会触发错误,因为主程序对类MY_PROJECT一无所知吗?

我愿意接受任何建议,因为我确实被卡住了。

编辑:
如果我有这个类在主程序中:

class BaseParent
{
public:
    virtual bool init(const TestCase&);
    virtual void run();
    virtual bool done();
}


接下来的两个类由创建项目的用户编写

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(...);
};


和另一类

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;
}


因此,我只能在主程序中包含BaseParent。如果Child类返回指向BaseParent的指针,那么我可以像下面这样调用init,done和run之类的方法?甚至那个BaseParent都不知道在运行中调用哪个execute?

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?
}


编辑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;
}


问题是链接器(在OS X上)给我一个错误:

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


但是在Ubuntu 12.04上我得到了:

(gdb)
99          AbsAlgorithm *a = (AbsAlgorithm*)create();
(gdb)

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()


因此,如上所示,该run和init方法是虚拟的。有什么建议吗?

最佳答案

UPD:我认为最正确的是

extern "C" BaseParent* create_object()
{
  return new Child;
}


因此,您可以保留Child完全存在于用户库中的事实,并且可以完全根据BaseParent提供库接口。

进行此更正后,此代码将起作用(只要它不包含其他错误,就不会检查其可编译性)。基本上,这就是多态性的关键思想:如果您有一个基类(接口)并且有一个派生类,并且某些代码仅使用该接口的方法,则该代码不需要知道有关该派生类的任何详细信息。 ,甚至都不知道派生类的存在。所有代码需要的是指向对象的指针,从该代码的角度来看,该指针将具有类似Interface*的类型,即将成为指向接口的指针。

09-10 19:27