我使用s支持 Adam Rosenfield 的解决方案map
。但是,获得更高级别功能的较低级别接口是使用dlsym()
查找。
假设您的通用Shape
接口位于文件中Shape.hpp
并具有以下形式:
class Shape {
public:
virtual ~Shape () {}
//...virtual methods
virtual void draw () const = 0;
};
template <typename DERIVED>
class ShapeBridge : public Shape {
public:
static Shape * create () { return new DERIVED; }
};
struct ShapeFactory {
Shape * (*create) ();
};
假设您想通过创建一个新的共享对象来动态添加一个新形状,然后将其动态链接到您现有的正在运行的可执行文件中。然后,您现在可以创建各种抽象工厂,它使用共享对象的动态加载来获取具体的工厂函数:
#include <string>
#include <map>
#include <dlfcn.h>
struct ShapeCreator {
void *dlhandle_;
void *factory_;
ShapeCreator () : dlhandle_(0), factory_(0) {}
void open (std::string libname) {
dlhandle_ = dlopen(libname.c_str(), RTLD_LAZY);
factory_ = dlsym(dlhandle_, "factory");
}
void close () { if (dlhandle_) dlclose(dlhandle_); }
ShapeFactory * factory () const {
return static_cast<ShapeFactory *>(factory_);
}
static Shape * create (std::string name) {
static std::map<std::string, ShapeCreator> lookup;
static std::string dir = "./";
if (lookup[name].factory() == 0) {
lookup[name].open(dir + name + ".so");
}
return lookup[name].factory()->create();
}
};
您的共享对象可能具有以下实现:
// gcc -fPIC -shared -Wl,-export-dynamic -o Circle.so Circle.cpp -lc
#include "Shape.hpp"
#include <iostream>
class Circle : public ShapeBridge<Circle> {
public:
//..
void draw () const { std::cout << "I am a circle.\n"; }
};
extern "C" {
ShapeFactory factory = { Circle::create };
}
然后动态创建形状:
Shape *s = ShapeCreator::create("Circle");
s->draw();
当然,如果该示例实际上是动态获取其名称的(例如从配置文件或从用户输入),则该示例会更有趣。