静态编译和链接时保留共享库插件系统的结构

问题描述:

对于我正在开发的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中的代码?

+0

我会用静态初始化(惨败)的路线。 –

+0

但是大多数情况下,这是失败的 –

+1

你的意思是在一些模板机制中注册到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); 
+0

之前实例化的,所以,讨厌的静态对象=模板实例化,调用register的构造函数?我想我应该尝试一下,但注意.o文件不链接,除非明确引用,使用链接器选项,请参阅 http://*.com/questions/9549714/trying-to-force-static-object-初始化 –

+0

某些类与ctor,是的,'模板'部分是可选的,但可以得心应手 –

+0

你可以举个例子吗?如果映射对于Core lib是本地的,那么我可以肯定它会在第一次注册时创建,或者如果没有人注册,将会被核心代码发现为空,导致没有插件被链接? –