静态编译和链接时保留共享库插件系统的结构
对于我正在开发的C++库,我已经看到了基于共享库的插件系统的优点。只要在初始化时扫描的目录中的一个共享库提供该功能,该功能就可供该库的用户使用。静态编译和链接时保留共享库插件系统的结构
使用dlopen,共享库将被搜索两个符号:一个函数返回命名他们实现的功能的字符串,一个创建函数实例化类并返回一个指向basse类的指针。事情是这样的:
在图书馆一
#include "Instance.hpp"
extern "C" const char* type() {
return "InstanceA";
}
//... class InstanceA definition, inherits from Instance
extern "C" Instance* create() {
return new InstanceA();
}
核心库将扫描插件目录,并保持地图与字符串> pointerToCreateFunction以创建新实例。
这真的很方便,而且是非常标准的事情。如果用户代码尝试实例化一个InstanceX,但没有共享库实现该类型,则会给出错误,所有内容都可以正常工作。
但是这个框架也将用于iOs开发,而App Store不允许加载第三方共享对象。即使加载静态链接插件的库的自包含版本,我也想保留这个模块化插件结构。请注意,在项目管理级别,这与在CMake中定义一个创建插件的静态版本并将其静态链接的变量一样简单。这也会排除代码的动态加载部分。
我缺少的是如何颠倒机制:虽然对于共享对象,核心库将利用文件系统来了解可以使用的实例类型,但我不知道如何“注册“他们没有改变大部分代码,也没有进入静态初始化失败。貌似有,唯一的办法是subsituting,扫描类型,并通过包括所有可能的头并具有很大的开关一样
Instance* theInstance;
if (instanceRequired == "instanceA")
theInstance = new InstanceA();
etc etc...
的创建函数你有办法避免,包括任何想法的代码所有标题,并且每次添加新实例时必须更改Core中的代码?
我通过那些在ctor中调用注册的讨厌的静态对象来做这样的事情。
通过使地图本身成为本地静态来避免排序问题,因此无论它来自何处,都会在第一次客户端调用时构建。 (线程和类似的问题被限制线程启动,直到-主要时间躲闪,到那个时候所有重要的事情是被迫。)
class RegMap; // the registry
RegMap& GetRegistry(); // the singleton access function; you can make a separate const/nonconst version or provide another wrapper for registering
// implementation in core.cpp:
RegMap& GetRegistry()
{
static RegMap m;
return m;
}
//in client ctor:
GetRegistry().Register(key, func);
之前实例化的,所以,讨厌的静态对象=模板实例化,调用register的构造函数?我想我应该尝试一下,但注意.o文件不链接,除非明确引用,使用链接器选项,请参阅 http://stackoverflow.com/questions/9549714/trying-to-force-static-object-初始化 –
某些类与ctor,是的,'模板'部分是可选的,但可以得心应手 –
你可以举个例子吗?如果映射对于Core lib是本地的,那么我可以肯定它会在第一次注册时创建,或者如果没有人注册,将会被核心代码发现为空,导致没有插件被链接? –
我会用静态初始化(惨败)的路线。 –
但是大多数情况下,这是失败的 –
你的意思是在一些模板机制中注册到Core中的地图(有很多)?我怎么知道地图是在我的模板是 –