2009-06-15 69 views
1

作爲一家公司計算機視覺部門的軟件開發人員,我一直工作一年。我的主要工作是將第三方軟件集成到一個框架中,所以我通常最終編寫包裝庫,因爲很多第三方軟件不能按照我們希望的方式工作(不是線程安全的,a * *使用等)。關於包裝第三方庫的建議

正常情況下,我只是包裝整個圖書館,並保持對圖書館的相互排斥(線程安全是大多數extern庫的主要問題)的調用。我非常喜歡這樣做,因爲它會讓你進入很多有趣的場景,並且你會看到很多有趣的代碼。然而,我經常認爲我做得不好,或者我的執行不太好。我覺得我缺乏一些關於如何正確做這些事情的設計知識。

基本上我想知道是否有任何關於設計一個合適的'API ontop破API'的好的指導方針或提示,或者如果這總是相當的hackish和醜陋。

回答

5

我引用的答案,另一個問題就在這裏前些天:

  1. 請問您目前的方法通過測試?
  2. 速度夠快嗎?

如果是,請繼續做你正在做的事情。

作爲替代

只要確保你的新的API既包括預期功能,並在原有的傳統意外功能。同時確保它呈現'適合用途'重新演示。查看FOSS項目中C庫的C++包裝,例如GTK/GTK for C++(它只是包裝前者)。

如果API被破壞,修復並提交補丁......與第三方(我假設有權訪問源意味着他們不會介意這個)寫一些他們的API是'包裝友好',並建議他們合併一些變化。如果有問題,請解決它。

沒什麼大不了的,只是用A包住B,並確保B做到了A應該或者被用來做什麼。

+0

謝謝,不知怎的,增強了我的信心;) 我通常不會遇到任何速度或語義問題,但通常的代碼是不乾淨,我希望它是。但我想沒有其他方法,因爲我沒有第三方庫的來源。 – tr9sh 2009-06-15 01:13:54

2

我可以添加到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); 

我已經看到了這個包裹在一個C++類的方式如下:

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類沒有真正使API更容易使用,甚至清潔恕我直言。如果遇到類似案例,然後:

  1. 使用完全參數的構造函數,以確保無效的情況下沒有在析構函數存在
  2. 清理所有資源
  3. 寫拷貝構造函數和賦值運算符,如果他們有意義使他們私人,並沒有實施他們。

我的目標是確保我提供的任何API /創建/包裝都適用於我們現有的編碼風格。我也嘗試將API彎曲成比目前更多的OO風格。我已經看到了一些我稱爲的面向對象C,就像我上面介紹的一樣。如果你想讓它們真正適合C++,那麼就要真正面向對象並利用C++提供給你的優勢:

  • 要小心地管理任何狀態變量。
  • 如果複製等操作沒有意義,請隱藏它們。
  • 如果有任何泄漏資源的可能性,然後找到一些方法來防止它發生(通常採用RAII幫助)。
  • 限制使用構造函數創建實例以消除無效實例和其他邊界情況。
+0

謝謝,我認爲這是一些非常好的建議,尤其對我來說,因爲我擁有強大的C背景,所以我對C++來說是相當新的。 – tr9sh 2009-06-15 07:54:59