2013-03-26 57 views
10

在像OpenCV這樣已建立完善的C++庫中添加或修改單個類方法的最佳實踐是什麼,同時仍然重用剩餘的庫代碼,最好以lib格式。部分更改C++庫,同時保持庫的其餘部分不變的最佳實踐

在這一點上,我知道的唯一方法是將屬於特定庫(讓我們說OpenCV的核心庫)的所有源文件和頭文件複製到當前的源文件夾,修改該函數並重新編譯模塊其餘的代碼。理想情況下,我希望能夠按照它們的方式鏈接所有當前的.lib文件,但只需爲這些庫中定義的類定義一個新方法(或修改當前方法),以便我的方法取代該方法執行默認的庫文件。

繼承似乎並不總是一種選擇,因爲有時基類具有正確的繼承類實現所需的私有成員。

回答

7

我不知道C++中的乾淨方式來完成你所要求的。你真正想要做的事情(考慮到你需要使用或修改私有方法)違反了封裝,而C++語言旨在不讓你這樣做。

有幾個選項存在:

  • 一個.lib文件是一個簡單的.obj文件的集合。您的編譯器工具鏈應該有一個命令行程序,用於添加,刪除和替換.lib中的.obj文件,以便您可以構建一個或兩個.obj文件並將它們合併到.lib中。我懷疑這個解決方案會是醜陋而脆弱的。
  • 如果圖書館沒有做和應該做的事情,那麼總是有機會向圖書館作者提交修補程序或功能請求以獲得所做的更改。當然,如果它工作的話,這可能需要一段時間。
  • 由於@fatih_k暗示,添加您的更改作爲朋友類將工作。如果只有更改您對OpenCV所做的更改是將friend行添加到頭文件中,那麼該庫的ABI將保持不變,您將不必觸摸.lib
  • 最簡潔的選擇是簡單地接受你需要修改OpenCV庫並跟蹤它的源代碼和修改,以及你自己開發的源代碼,並將它與自己構建的源代碼一起構建。這是一種非常普遍的方法,並且存在各種模式和技術來幫助您做到這一點;例如,Subversion具有vendor branches的概念。這種方法是更多的工作,但從長遠來看絕對是最乾淨的。
+0

優秀點。我肯定從這篇文章中學到了很多東西。謝謝。 – Bee 2013-03-26 15:38:19

1

那麼,OpenCV是在BSD下許可的,所以你可以做你的修改而不用擔心重新發布它們。

您可以隨時遵循代理設計模式,並在庫外部添加新方法,並從那裏調用庫。這意味着你不需要擔心維護自己的OpenCV版本並分發它。 There's more information about Proxy patterns on Wiki讓你開始。

+0

感謝您的回答。不幸的是,代理設計不能解決私人成員問題。具體而言,我想修改OpenCV中的類的當前方法,以不同方式處理內部(有時是私有的)成員。代理似乎讓我做額外的預處理,但真正的類的基礎邏輯保持不變。 – Bee 2013-03-26 15:30:48

+0

對不起,我沒有意識到你正試圖修改私人會員資料。 – 2013-03-26 15:41:40

2

如果庫已經編譯完成,那麼你可以做的並不多,乾淨利落。

如果您知道該程序將運行的特定目標體系結構,則可以獲取指向該成員函數的指針,然後使用jmp指令將指令添加到您自己版本的方法中。如果該方法是虛擬的,則可以修改vtable。這些需要大量編譯器特定的知識,並且不能移植。

如果庫船舶動態鏈接的歸檔,你可以提取存檔,並用自己的版本替換方法,以及重新包裝存檔。

另一種方法是你可以從標題複製類的聲明,並添加好友聲明。或者,在包含頭文件之前,您可以執行#define private public#define private protected。這些將使您可以訪問其私人會員。

在進行上述的,你要小心,你的變化不修改庫的ABI。

+0

謝謝!有趣和有益的想法,雖然對於這個特定的任務太多了。 OpenCV是開源的,我最初將源代碼編譯到它們各自的庫中,因此編輯庫源代碼不成問題。我只是想看看其他人在這樣的情況下做些什麼。 – Bee 2013-03-26 15:36:31