Как лучше всего создать библиотеку из существующих функций?
Мне было поручено взять работающие функции и создать библиотеку с этими функциями.
Взгляните на следующую функцию, существовавшую внутри программы:
char* Num_to_HEX_char_array(int32_t value)
{
Clear_array(MyTempArray, MY_TEMP_ARRAY_LENGTH);
ltoa(value, MyTempArray, HEX);
return MyTempArray;
}
(Проигнорируем тот факт, что эта функция)
Его нельзя сразу превратить в библиотеку, так как MyTempArray
не существует.
Это, в файле .cpp
, мне придется вручную создать эти строки:
#define MY_TEMP_ARRAY_LENGTH 20
char MyTempArray[MY_TEMP_ARRAY_LENGTH];
Теперь библиотека компилируется нормально. Однако эта библиотека может вызываться многими программами, которые я создаю, и некоторым из них может потребоваться другая длина массива, а другим требуется имя, отличное от этого.
Как лучше всего создать эту библиотеку?
*Одним из подходов, который я придумал, было динамическое создание этих массивов с помощью malloc()
.
И затем в основной программе вам нужно будет realloc()
массивы с теми, которые вы хотите.
Также используйте undef
и пере#define
.
Недостаток этого подхода заключается в том, что вы должны ВСЕГДА использовать эти операторы, если хотите, чтобы ваша библиотека работала
*Другой подход заключается в размещении всего этого кода:
#define MY_TEMP_ARRAY_LENGTH 20
char MyTempArray[MY_TEMP_ARRAY_LENGTH];
внутри файла заголовка конфигурации. Переменные будут иметь глобальную область видимости. Тогда при создании приложения вам останется только изменить этот файл.
Мой вопрос к этому подходу: как именно вы можете убедиться, что этот файл конфигурации читается всеми библиотеками?
Возможно, у вас много библиотек, например, обработка строк или обработка датчиков...
Каждая из этих библиотек, созданных пользователями, должна #include
просмотреть этот заголовочный файл конфигурации, чтобы убедиться, что определения и массивы имеют правильное имя и размер.
Как сделать так, чтобы его видели все ваши пользовательские библиотеки?
Где оптимально разместить этот файл?
Вообще, как лучше всего решить эту проблему?
@user1584421, 👍-1
Обсуждение3 ответа
Я бы написал такую функцию, ожидающую, что вызывающая функция выделит массив и передаст его и его размер в качестве аргументов. Таким образом, выделение и освобождение памяти остается на усмотрение каждого пользователя библиотеки, который может захотеть/нужно (по другим причинам) использовать статический массив, динамическую память или автоматический массив и позволяет им освобождать ее (или нет), когда их приложению это больше не нужно. Кодирование этих данных в вашей библиотеке ограничит ее использование.
Прежде всего, я должен сказать, что у меня есть проблема с приведенным вами примером.
Функция Num_to_HEX_char_array()
должна использовать массив с
максимальный размер, который может когда-либо понадобиться ltoa()
. Не больше, не меньше. Здесь нет
указать на то, чтобы позволить пользователю библиотеки выбрать этот размер. Вот как я
будет реализовывать эту функцию:
char *Num_to_HEX_char_array(int32_t value)
{
static char buffer[2 * sizeof(long) + 1];
return ltoa(value, buffer, HEX);
}
При этом я согласен с тем, что в вашей библиотеке есть некоторые статические буферы, для которых имеет смысл позволить пользователю выбирать размер. Вероятно, вы могли бы найти лучший пример, чтобы поместить его в хотя вопрос.
В этом случае я бы посоветовал вам сначала рассмотреть предложенный подход
JRobert, и пусть пользователь предоставляет эти буферы. Использование статических буферов
в библиотеке может упростить использование API в наиболее распространенных случаях.
В стандартной библиотеке C есть много функций, которые делают это, например:
например, ctime()
. Однако за это приходится платить:
пользователь должен быть хорошо осведомлен о том, что обращения к библиотеке могут данные, возвращенные предыдущими вызовами
функции не допускают повторного входа, то есть их нельзя использовать в несколько потоков, и они не могут использоваться как в прерывании, так и в контексты без прерывания.
Вот почему у вас есть такие функции, как ctime_r()
: предоставить
альтернатива, которая позволяет пользователю управлять буфером и не страдает
от предыдущих недостатков.
Если вы все еще считаете, что вам нужны статические буферы в вашей библиотеке, тогда
вы должны сначала подумать, можно ли исправить размер, например
в примере Num_to_HEX_char_array()
. Если это невозможно, то
лучшее, что я могу придумать, это использовать шаблоны C++. Например:
template<size_t size> class CircularBuffer {
int buffer[size];
// ...
};
который будет создан следующим образом:
// Пусть `queue' будет циклическим буфером на 42 слота.
CircularBuffer<42> queue;
Имейте в виду, однако, что этот метод вынуждает вас помещать большую часть код в заголовочном файле.
Компиляторы командной строки и большинство IDE для C и C++ позволяют задавать определения проекта как параметры -D в настройках проекта. В Arduino IDE это еще не реализовано, потому что в нем нет файла конфигурации проекта.
С помощью Arduino IDE вы можете добавлять определения для платформы или для определений платы с помощью build.extra_flags в файле platform.local.txt или boards.local.txt. Пример для boards.local.txt для Arduino Mega:
mega.build.extra_flags=-DUIP_CONF_UDP_CONNS=20 -DUIP_CONF_MAX_LISTENPORTS=30
platform.local.txt и boards.local.txt должны находиться в папке пакета boards, а не platform.txt и boards.txt.
- Ошибка: invalid application of 'sizeof' to incomplete type 'int []' при попытке вычислить размер массива в библиотеке
- Как масштабировать растровое изображение (массив uint8_t) в Arduino?
- Разбор массива объекта в конструкторе библиотеки
- Создание массива с длиной, полученной из библиотеки
- Как получить исходные файлы для библиотек Arduino?
- Ошибка: "недопустимое использование нестатической функции-члена" при вызове функции из моего собственного класса-метода
- Как подключить Wi-Fi Shield ESP-12E-ESP8266-UART-WIFI-Wireless-Shield к Arduino
- Возможно ли иметь массив массивов int?
что вы имеете в виду, когда говорите «лучший»?, @jsotola