Лучшая практика частично изменить библиотеку С++, оставив остальную библиотеку неповрежденной

Какова наилучшая практика добавления или изменения метода одного класса в хорошо установленной библиотеке С++, такой как OpenCV, при повторном использовании оставшегося кода библиотеки, предпочтительно в формате lib.

В этот момент единственным способом, который я знаю, является копирование всех исходных и заголовочных файлов, принадлежащих конкретной библиотеке (скажем, базовой библиотеки OpenCV), в текущую исходную папку, изменение этой функции и перекомпиляцию модуля с остальными кода. В идеале я хочу иметь возможность связывать все текущие .lib файлы так, как они есть, но просто определить новый метод (или изменить текущий метод) для класса, определенного внутри этих библиотек, таким образом, что моя реализация метода заменяет реализация файлов библиотеки по умолчанию.

Наследование не всегда представляется опцией, так как иногда базовый класс имеет частные члены, которые необходимы для правильной реализации наследуемого класса.

Ответ 1

Я не знаю о чистом виде на С++, чтобы выполнить то, что вы просите. То, что вы действительно просите (учитывая, что вам нужно использовать или модифицировать частные методы), нарушает инкапсуляцию, а язык С++ предназначен для того, чтобы вы этого не делали.

Существует несколько вариантов:

  • Файл .lib представляет собой просто набор файлов .obj. Ваша инструментальная цепочка компилятора должна иметь программу командной строки для добавления, удаления и замены файлов .obj в .lib, поэтому вы можете создать один или два файла .obj и объединить их в .lib. Я подозреваю, что это решение было бы уродливым и хрупким.
  • Если что-то, что библиотека не делает и что делать, всегда есть шанс, что вы можете отправить исправление или запрос функции авторам библиотеки, чтобы получить это изменение. Конечно, это может занять некоторое время, если оно вообще работает.
  • Как @fatih_k предлагает добавить ваши изменения в классы друзей. Если единственное изменение, которое вы делаете в OpenCV, заключается в том, чтобы добавить строку friend в заголовочный файл, тогда библиотека ABI не изменится и вам не нужно прикасаться к .lib.
  • Самый чистый вариант - просто принять, что вам нужно изменить библиотеку OpenCV и отслеживать его исходный код вместе с вашими изменениями вместе с исходным кодом, который вы разрабатываете самостоятельно, и построить его вместе с исходным кодом, который вы сами создаете. Это очень распространенный подход, и существуют различные шаблоны и методы, которые помогут вам это сделать; например, Subversion имеет концепцию ветки поставщика. Этот подход больше подходит для настройки, но, безусловно, является самым чистым в долгосрочной перспективе.

Ответ 2

Если библиотека уже скомпилирована, вы не можете сделать ее портативно и чисто.

Если вы знаете конкретную целевую архитектуру, на которой будет запущена программа, вы можете получить указатель на функцию-член, а обезьяна исправить инструкции с помощью инструкции jmp для вашей собственной версии метода. Если этот метод является виртуальным, вы можете изменить vtable. Это требует большого количества специфических для компилятора знаний и не будет переносимым.

Если библиотека отправляется в архив динамической ссылки, вы можете извлечь архив и заменить метод своей собственной версией и переупаковать архив.

Другой метод - вы можете скопировать объявление класса из заголовка и добавить объявление друга. В качестве альтернативы вы можете сделать #define private public или #define private protected, прежде чем включать файл заголовка. Они предоставят вам доступ к своим частным членам.

С любым из вышеперечисленных вопросов вам нужно быть осторожным, чтобы ваши изменения не изменяли ABI библиотеки.

Ответ 3

Ну, OpenCV лицензируется под BSD, поэтому вы можете внести свои изменения, не опасаясь переиздания их.

Вы всегда можете следовать шаблону проектирования прокси и добавить новый метод, внешний для библиотеки, и позвонить в библиотеку оттуда. Это означает, что вам не нужно беспокоиться о сохранении собственной версии OpenCV и ее распространении. Более подробную информацию о шаблонах прокси-сервера в Wiki, чтобы вы начали.