Как лучше вносить изменения в стороннюю библиотеку С?
Добрый день, подскажите стратегию поведения: есть существующая библиотека на С (libmodbus). Но нужно добавить некоторый функционал: переключать преобразователь в режим приема/передачи, для этого преусмотрено управление через gpio. Добавить получается только в существующую функцию. Собственно, вопрос в том, как, исходя из вашего опыта, лучше внести изменения, чтобы избежать больших проблем при дальнейшей поддержке? Пока созрело только два варианта: либо вносить изменения в существующий код, либо переписать функцию. Если переписывать, как лучше ее переопределить?
serhiops, Там идет цепочка вызовов, библиотека реализована обобщенно, чтобы можно было создавать различный функционал. Если писать нужную мне реализацию функций, все равно придется вставлять ее как-то в разрыв этих вызовов. Ну или переопределять указатели на вызываемые функции. В общем, и так и так нужно вносить код в исходную библиотеку.
переключать преобразователь в режим приема/передачи
Преобразователь это же ведомое устройство в modbus? А ваша программа, видимо выступает как контроллер?
Тогда вы должны с помощью библиотеки отправить на ведомое устройство некий пакет с конфигурацией. Я не в курсе, как там это в modbus конкретно работает, не имел с ним дела.
Универсальная библиотека в принципе не может обеспечить работу со всей массой устройств, поддерживающих modbus. Библиотека, видимо, реализует только низкоуровневый протокол обмена, который описан в каком-то стандарте. А верхний уровень вы должны реализовать в вашем приложении. Для этого не нужно изменять библиотеку.
Начните с изучения примеров к библиотеке (скачайте исходники, там есть тесты, их можно использовать в качестве примеров работы с библиотекой. Дальше - документация к библиотеке. Если захотите понять глубже, смотрите документацию на modbus.
res2001, под преобразователем я имел в виду микросхему преобразования типа MAX485 или подобное, которая осуществляет переход от логических уровней UART RX, TX к дифференциальному способу передачи сигналов RS485. При этом, передача осуществляется в полудуплексном режиме: нужно "вручную" переключать направление передачи или приема.
Грубо, библиотека отсылает запрос ведомому и ожидает от него ответа. Вот в этот момент и нужно вклиниться, переключая прием и передачу.
Кстати, пока писал, нашла мысль в голову, проверить реализацию CTS на моем модуле. (он используется в библиотеке именно для переключения). Отчего-то я решил, что на плате представлен только RX-TX. Но вроде как, CTS тоже можно назначить на GPIO. Вот как бывает, в обсуждении и объяснении задачи чаще всего находится решение. В любом случае, огромное вам всем спасибо, друзья!
kriptonus, Т.е. вам нужно адаптировать библиотеку под железо. Обычно в таких случаях в библиотеках выделяют уровень абстракции железа (HAL или OSAL обычно называется). Часто он идет как отдельная низкоуровневая библиотека в зависимостях основной библиотеки. Как правило это достаточно не большой API, который надо реализовать и который будет использовать библиотека верхнего уровня. Часто можно взять уже готовые похожие реализации и адаптировать их под себя.
Не знаю, есть ли в libmodbus свой HAL или получится с CTS. На сколько знаю, CTS часто используют для целей управления потоком приема/передачи в полудуплексном RS485.
Спасибо, буду разбираться, как это лучше реализовать
По наводке res2001 пересмотрел аппаратную реализацию UART, решение, похоже, нашлось. Осталось все проверить и убедиться в работоспособности. Всем огромное спасибо, друзья!
Ну а советы по общим принципам модификации сторонних библиотек я также отмечу для дальнейших действий. Всем успехов!
Непонятно, какие у этой библиотеки есть точки расширения, какие есть интерфейсы. Общий ответ всегда один - форкать, наливать сверху свои изменения и затем портировать их регулярно на свежий релиз. Это самый затратный вариант, но он не требует ничего от библиотеки кроме открытости кода и подходящей лицензии, разрешающей вносить правки без неприемлемых для вас обязательств.
Нужны подробности реализации. Если вы рассчитываете, что с вашей реализацией библиотеки должны работать и сторонние программы, то, как минимум, не надо ломать API при изменении функции.
Вариант реализации:
Сделать в функции два code path. Один - как был раньше. Другой - какой нужен. Переключение осуществлять по значению переменной окружения. Ещё один вариант - сделать переменную-переключатель. Это, конечно, неудачные варианты, но если программа работает в одном потоке то по принципу "и так сойдёт" - вполне будет работать.
Можно попробовать для своего случая подмену функции с помощью библиотеки, загружаемой через LD_PRELOAD. Тоже не самый лучший вариант, но можно рассмотреть.
Таки определить другую функцию и переписать кусочек программы. Оптимальный вариант.
1 вариант: если можете "всунуть" управление приёмом/передачей в "портовую" часть, то проще добавить свою папку порта с своими изменениями.
2 вариант: библиотеку в гит и свои изменения в отдельную ветку
3 вариант: 2 и 1 вариант если либмодбас например в гитхабе, то предложить пул реквест со своими изменениями