c++ - 在静态编译和链接时保持共享库插件系统的结构

标签 c++ gcc app-store static-libraries dynamic-linking

对于我目前正在开发的C++库,我已经看到了基于共享库的插件系统的优势。只要在初始化时扫描的目录中的共享库之一提供该功能,库的用户就可以使用该功能。

使用 dlopen,将在共享库中搜索两个符号:一个函数返回命名它们实现的功能的字符串,另一个创建函数实例化类并返回指向基类的指针。像这样:

在图书馆A

#include "Instance.hpp"
extern "C" const char* type() {
  return "InstanceA";
}
//... class InstanceA definition, inherits from Instance
extern "C" Instance* create() {
    return new InstanceA();
}

Core 库将扫描插件目录并保留映射字符串->pointerToCreateFunction 以创建新实例。

这真的很方便,而且是一件非常标准的事情。如果用户代码尝试实例化 InstanceX 但没有共享库实现该类型,则会给出错误,但一切都会正常运行。

但此框架也将用于 iOs 开发,App Store 不允许加载第 3 方共享对象。即使在加载静态链接插件的库的自包含版本时,我也想保留这种模块化插件结构。请注意,在项目管理级别,这就像在 CMake 中定义一个变量一样简单,该变量创建插件的静态版本并静态链接它们。这也将排除代码的动态加载部分。

我缺少的是如何反转机制:虽然对于共享对象,核心库将利用文件系统来了解可以使用的实例类型,但我不知道如何“注册”他们没有改变大部分代码,也没有进入静态初始化失败。看起来唯一的方法是通过包含所有可能的 header 并使用像

这样的大开关来替换扫描类型和创建函数的代码
Instance* theInstance;
if (instanceRequired == "instanceA") 
  theInstance = new InstanceA();
etc etc...

您是否想过一种方法来避免每次添加新实例时都包含所有 header 并不得不更改 Core 中的代码?

最佳答案

我通过那些在 ctor 中调用 register 的讨厌的静态对象来做这些事情。

通过使 map 本身成为本地静态来避免排序问题,因此无论 map 来自何处,都可以在第一次客户端调用时构建。 (通过将线程启动限制在 until-main 时间来避免线程和类似问题,到那时所有重要的事情都被强制执行。)


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

关于c++ - 在静态编译和链接时保持共享库插件系统的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17341113/

相关文章:

c++ - std::bitset - 如何迭代 "set"(或 "not set")位?

c++ - 所有Derived类都必须实现自己的析构函数,否则报编译错误?

c - 如何读取带有空格的scanf

c - "comparison between signed and unsigned integer expressions"仅包含无符号整数

c - 粘贴 ""Pushl $""和 ""1 5""时出错,未给出有效的预处理 token

ios - TestFlight 上传/发布是否会干扰 Apple App Store 发布的版本号

用于获取 JPEG 图像大小的 C++ 库

c++ - 使用#include "filename"时出现编译器错误

cordova - 由于 'Unauthorized',iOS Cordova/PhoneGap App Store 被拒绝

iphone - 二进制中的iPhone App图标