代码之家  ›  专栏  ›  技术社区  ›  tr9sh

包装第三方图书馆的建议

  •  1
  • tr9sh  · 技术社区  · 15 年前

    我在一家公司的计算机视觉部门做了一年的软件开发员。我的主要工作是将第三方软件集成到一个框架中,因此我通常以编写包装器库告终,因为很多第三方软件的工作方式都不符合我们的要求(线程不安全,使用起来很麻烦等等)。

    通常情况下,我只是包装整个库,并用互斥保护对库的调用(线程安全是大多数外部库的主要问题)。我真的很喜欢这样做,因为它让你进入很多有趣的情况,你会看到很多有趣的代码。然而,我经常认为我做得不好,或者我的实现不是很好。我觉得我缺少一些关于如何正确地做这些事情的设计知识。

    2 回复  |  直到 15 年前
        1
  •  5
  •   Aiden Bell    15 年前

    我将在前几天在这里引述另一个问题的答案 :

    1. 你目前的方法通过测试了吗?
    2. 够快吗?

    只需确保您的新API包含 预定的 功能和 依照惯例的 原版的功能。此外,还应确保其呈现“适合目的”的再呈现。窥视一下在FOS项目中C++库的C++封装,例如C++的GTK/GTK(它只封装了前者)。

    如果API损坏,请修复它并提交修补程序。。。与第三方打交道(我假设访问源代码意味着他们不会介意这一点)。。。您可以重新编写一些API,使其“包装友好”,并建议它们合并一些更改。如果有问题,由你来解决。

        2
  •  2
  •   Community CDub    8 年前

    我唯一能补充的是 Aiden's response 您还应该将需要显式初始化和终止的代码替换为 RAII 技术。当我面对在API上提供外观时,我似乎总是遇到这样一个类:

    struct ADVERTISER {
        /* a bunch of members here */
    };
    
    void adv_Initialize(ADVERTISER *adv, /* a bunch of arguments */);
    void adv_DoStuff(ADVERTISER *adv);
    void adv_Terminate(ADVERTISER *adv);
    

    namespace wrapper {
      class Advertiser {
      public:
          Advertiser(): inited_(false) {}
          void initialize(/* a bunch of arguments */) {
            terminate();
            adv_Initialize(&adv_, ...);
            inited_ = true;
          }
          void doStuff() {
            validate();
            adv_DoStuff(&adv_);
          }
          void terminate() {
            if (inited_) {
                adv_Terminate(&adv_);
                inited_ = false;
            }
          }
      protected:
          void validate() {
            if (!inited_) {
                throw std::runtime_error("instance is not valid");
            }
          }
      private:
          ADVERTISER adv_;
          bool inited_;
      };
    }
    

    问题是 Advertiser

    1. 使用完全参数化的构造函数确保不存在无效实例
    2. 清理析构函数中的所有资源
    3. 编写一个复制构造函数和赋值运算符(如果它们有意义的话) 将它们私有化,不要实施它们。

    我的目标是确保我展示/创建/包装的任何API都能与我们现有的编码风格兼容。我还尝试将API转变为一种比目前更具OO风格的风格。我看过很多我称之为 就像我上面介绍的那个。如果你想让它们真正融入C++,那么就要真正面向对象,并利用C++给你的优势:

    • 小心管理任何状态变量。
    • 如果有任何资源泄漏的可能性,那么找到一些方法来防止它的发生(通常使用RAII会有所帮助)。