Как использовать RAII с сишным API
Все мы с вами используем сишный API. Базы данных, работа с сетью, криптография. Перечислять области можно долго. И все мы с вами немного недолюбливаем такой способ взаимодействия с сущностями. Оно и понятно. Не зря умные дяди придумывали объектно-ориентированное программирование и не зря мы, не такие умные дяди, стараемся этой методологии следовать. А тут нужны какие-то сырые указатели, байтовые буфферы и прочие вульгарности. Это не только неудобно, но может приводить к трудноотловимым ошибкам, недостаточной гарантии безопасности. Старшие ребята, естественно, знают, как правильно использовать плюсовые объекты в таких случаях, а вот молодняк может не знать этого или не осознавать подходов, которые они использовали. Поэтому поделюсь своей интерпретацией адекватного подхода, который поможет грамотно использовать RAII с сишным апи.
На помощь нам неожиданно приходят std::array и std::vector. Это простые RAII обертки над статическими и динамическими массивами, которые предлагают следующие фичи:
1️⃣ Автоматическое управление памятью. std::array в конструкторе аллоцирует память на стеке, std::vector - на куче. Их деструктор вызывается при выходе из скоупа.
2️⃣ Детерминированная инициализация. Инициализация этих контейнеров происходи в конструкторе, что предотвращает обращение к неинициализированной памяти.
3️⃣ Безопасный и удобный доступ к элементам с помощью методов .at(), .back(), .front() и итераторов.
4️⃣ Легкий доступ к буферу через метод .data().
Как их использовать для взаимодействия с С API? Гениально и просто.
👉🏿 Объявить нужный массив. Если размер структуры известен на момент компиляции - std::array, если нет - std::vector. Инициализировать его в конструкторе нужными значениями: дефолтовыми - в конструкторе, кастомными - через memcpy(array_ptr, struct_ptr, struct_size).
👉🏿 Передать в Сишный апи. Например так:
AES_cbc_encrypt(plaintext_array.data, ciphertext_array.size(), plaintext_array.size() ...);
👉🏿 Наслаждаться жизнью, ибо больше вам не нужно ни о чем беспокоиться.
Если уж вы передаете в С API более сложные структуры, чем массивы, то вам могут понадобиться методы сериализации и десериализации.
Используя возможности RAII массивов вы можете упростить и оптимизировать свой код, гарантировать правильное управление памятью и безопасную передачу данных в С API.
Делитесь своим опытом взаимодействия с API C и используйте modern C++ для более надежного и эффективного кода.
Stay cool.
#goodoldc #design #cppcore #STL
Все мы с вами используем сишный API. Базы данных, работа с сетью, криптография. Перечислять области можно долго. И все мы с вами немного недолюбливаем такой способ взаимодействия с сущностями. Оно и понятно. Не зря умные дяди придумывали объектно-ориентированное программирование и не зря мы, не такие умные дяди, стараемся этой методологии следовать. А тут нужны какие-то сырые указатели, байтовые буфферы и прочие вульгарности. Это не только неудобно, но может приводить к трудноотловимым ошибкам, недостаточной гарантии безопасности. Старшие ребята, естественно, знают, как правильно использовать плюсовые объекты в таких случаях, а вот молодняк может не знать этого или не осознавать подходов, которые они использовали. Поэтому поделюсь своей интерпретацией адекватного подхода, который поможет грамотно использовать RAII с сишным апи.
На помощь нам неожиданно приходят std::array и std::vector. Это простые RAII обертки над статическими и динамическими массивами, которые предлагают следующие фичи:
1️⃣ Автоматическое управление памятью. std::array в конструкторе аллоцирует память на стеке, std::vector - на куче. Их деструктор вызывается при выходе из скоупа.
2️⃣ Детерминированная инициализация. Инициализация этих контейнеров происходи в конструкторе, что предотвращает обращение к неинициализированной памяти.
3️⃣ Безопасный и удобный доступ к элементам с помощью методов .at(), .back(), .front() и итераторов.
4️⃣ Легкий доступ к буферу через метод .data().
Как их использовать для взаимодействия с С API? Гениально и просто.
👉🏿 Объявить нужный массив. Если размер структуры известен на момент компиляции - std::array, если нет - std::vector. Инициализировать его в конструкторе нужными значениями: дефолтовыми - в конструкторе, кастомными - через memcpy(array_ptr, struct_ptr, struct_size).
👉🏿 Передать в Сишный апи. Например так:
AES_cbc_encrypt(plaintext_array.data, ciphertext_array.size(), plaintext_array.size() ...);
👉🏿 Наслаждаться жизнью, ибо больше вам не нужно ни о чем беспокоиться.
Если уж вы передаете в С API более сложные структуры, чем массивы, то вам могут понадобиться методы сериализации и десериализации.
Используя возможности RAII массивов вы можете упростить и оптимизировать свой код, гарантировать правильное управление памятью и безопасную передачу данных в С API.
Делитесь своим опытом взаимодействия с API C и используйте modern C++ для более надежного и эффективного кода.
Stay cool.
#goodoldc #design #cppcore #STL