libnumerixpp
0.1.3
A Powerful C++ Library for High-Performance Numerical Computing
|
В мире программирования создание собственных библиотек - это не просто возможность пополнения своего портфолио или способ структурировать код, а настоящий акт творческого самовыражения (и иногда велосипедостроения). Каждый разработчик иногда использовал в нескольких своих проектах однообразный код, который приходилось каждый раз перемещать. Да и хотя-бы как упаковать свои идеи и знания в удобный и доступный формат, которым можно будет поделиться с сообществом.
Если вы ловили себя на мысли: "А почему мне бы не создать свою полноценную библиотеку?", то я рекомендую прочитать вам мою статью.
Эту статью вы можете использовать как шпаргалку для создания проектов, и не только библиотек.
Некоторые из вас могут подумать что мы изобретаем велосипед. А я в ответ скажу - сможете ли вы прямо сейчас, без подсказок, только по памяти, нарисовать велосипед без ошибок?
Сразу говорю - я не профессионал в C++, и вы всегда можете поправить меня в комментариях. Благодарю!
Язык программирования С++ представляет высокоуровневый компилируемый язык программирования общего назначения со статической типизацией, который подходит для создания самых различных приложений. На сегодняшний день С++ является одним из самых популярных и распространенных языков.
Своими корнями он уходит в язык Си, который был разработан в 1969—1973 годах в компании Bell Labs программистом Деннисом Ритчи (Dennis Ritchie). В начале 1980-х годов датский программист Бьерн Страуструп (Bjarne Stroustrup), который в то время работал в компании Bell Labs, разработал С++ как расширение к языку Си. Фактически вначале C++ просто дополнял язык Си некоторыми возможностями объектно-ориентированного программирования. И поэтому сам Страуструп вначале называл его как "C with classes" ("Си с классами"). Но называть его так - значит упускать много конструкций из виду. Помимо ООП, есть пространства имен, шаблоны, огромная стандартная библиотека и так далее. В принципе, я думаю, не надо углубляться в историю языка. Но стоит знать, что с 1998 до 2011 года C++ развивался довольно медленно, но в 2011 вышел стандарт C++11, в котором было реализовано множество нового функционала.
С++ повсюду. Код, написанный на C++, можно найти в вашем телефоне, в вашей стиральной машине, в вашем автомобиле, в самолетах, в банках и вообще везде, где только можно представить.
Одной из важнейших особенностей C++ является предсказуемое управление памятью. Тут нет сборки мусора, которая в конечном итоге происходит (или нет). Когда и как память будет освобождена и возвращена операционной системе - абсолютно детерминировано. Хотя все всегда было абсолютно детерминировано, было также довольно легко выстрелить себе в ногу и испортить все, не высвобождая память или наоборот пытаясь высвободить ее дважды или даже больше раз...
А также C++ невероятно экономичен и быстрый. Посмотрите на довольный известный график снизу:
Ну а теперь к минусам. Один из главных минусов, который влияет на популярность C++ - плохая реклама. Многие люди настроены негативно по отношению к C++, из-за его сложности. Сколько раз вы слышали "с C легко выстрелить себе в ногу. В C++ это сложнее, но зато вы отстреливаете всю ногу сразу"?
Также довольно большим минусом является отсутствие экосистемы стандартизированных инструментов. Например, доставка и использование библиотек. В JavaScript для этого используется npm, в Python pip, в Haskell есть stack и cabal. То есть у этих языков есть экосистема, которая позволяет без сложностей использовать и публиковать пакеты, и в принципе работать с языком. А у C++ нет таких инструментов-стандартов. Есть конечно Conan, vcpkg, но они мало развиты, и разобщены.
Тем не менее, язык и экосистема растут, сообщество очень большое, а C++ неизбежно повсеместен. Так или иначе, его хотя бы частично можно найти почти в каждом написанном на сегодня программном обеспечении. Я не говорю, что C++ — это молоток, который должен превратить все вокруг вас в гвозди, но его все же стоит изучить и освоить.
Прошу не начинать холивары в комментариях насчет C++, эта статья туториал, а не обзор.
Теперь можно перейти к тому, что делает этот язык уникальным. Какие специфические особенности отличают C++ от C и других языков, и как они влияют на процесс разработки.
Начнем с относительно легкой вещи - а именно пространства имен. Я не буду сильно углубляться в темы, просто расскажу минимальную информацию. Мы же все таки айтишники, а не сосиски в тесте.
Пространство имен позволяет сгруппировать функционал в отдельные контейнеры. Пространство имен представляет блок кода, который содержит набор компонентов (функций, классов и т.д.) и имеет некоторое имя, которое прикрепляется к каждому компоненту из этого пространства имен. Полное имя каждого компонента — это имя пространства имен, за которым следует оператор :: (оператор области видимости или scope operator) и имя компонента. Примером может служить оператор cout, который предназначен для вывода строки на консоль и который определен в пространстве имен std. Соответственно чтобы обратиться к этому оператору, применяется выражение std::cout.
Но также можно создавать и свои пространства:
Директива using позволяет ссылаться на любой компонент пространства имен без использования его имени:
А также можно делать псевдонимы:
Объектно-ориентированное программирование - очень обширная область. Имеет множество псевдоформальных формулировок написанными людьми разной степени эксперности. Множество принципов, паттернов делают ООП сложным для понимания новичкам.
У нас статья не об ООП, так что сильно углубляться не будем. Вот пример класса:
C++ позволяет определять функции с одним и тем же именем, но разным набором параметров. Подобная возможность и называется function overloading. Компилятор уже сам выбирает нужный тип функции.
При этом различные версии функции могут также отличаться по возвращаемому типу. Однако компилятор при выборе ориентируется именно на кол-во параметров и их тип.
Простейший пример:
Функции могут отличаться и количеством аргументом, и их типом и так далее.
Но стоит учитывать что функция с параметрами-ссылками и обычными параметрами считаются одинаковыми. Но если в одной функции параметр является константой и ссылкой/указателем, то эти функции уже будут различаться компилятором.
Концепция шаблонов возникла из известного принципа программирования DRY (Dont't repeat yourself, не повторяйся). Шаблоны позволяют определить конструкции, которые используют определенные типы, но на момент написания кода точно не известно, что это будут за типы. То есть, шаблоны позволяют определить универсальные конструкции, которые не зависят от конкретных типов.
Полностью шаблоны расписывать не буду, а порекомендую прочитать эту статью. В ней наиболее полно рассказывается о всех возможностях шаблонов.
C++ имеет следующий вид функции с принятием аргументов:
Каждая уважающая себя библиотека должна иметь три вещи:
Не буду расписывать создание репозитория, и почему нужно использовать git-репозиторий, думаю вы это знаете. Моя цель показать примерную структуру проекта.
Один из самых важных файлов - .gitignore
. Этот файл содержит в себе список директорий и файлов, которые следует игнорировать. Вот мой .gitignore из моего репозитория:
А также нам нужно будет создать файл .github/workflows/static.yml, но это будет позже, когда мы будем создавать документацию.
Сама структура проекта такова:
Рассмотрим ее:
CMake — кроcсплатформенная утилита для автоматической сборки программы из исходного кода. При этом сама CMake непосредственно сборкой не занимается, а представляет из себя front-end. В качестве back-end'a могут выступать различные версии make и Ninja. Так же CMake позволяет создавать проекты для CodeBlocks, Eclipse, KDevelop3, MS VC++ и Xcode.
Для того что бы собрать проект средствами CMake, необходимо в корне дерева исходников разместить файл CMakeLists.txt, хранящий правила и цели сборки, и произвести несколько простых шагов.
Больше о CMake вы можете прочитать в этой статье.
Инструкция по сборке cmake хранится в файле CMakeLists.txt:
Код выше - это и есть файл сборки CMake моего проекта. Рассмотрим его:
cmake_minimum_required
- минимальная версия CMakeproject(libnumerixpp VERSION 0.1.0)
- название и версия проектаset(CMAKE_CXX_STANDARD 17)
- устанавливаем стандарт C++17set(CMAKE_CXX_STANDARD_REQUIRED ON)
- требуем чтобы компилятор поддерживал выбранный стандарт C++set (EXECUTABLE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
- устанавливаем каталог вывода для исполняемых файловset(LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin)
- устанавливаем каталог вывода для библиотекfile(GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
- находим все C++ файлы в директории srcfile(GLOB_RECURSE EXAMPLE_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/examples/*.cpp)
- находит все C++ файлы в директории examplesadd_library(libnumerixpp SHARED ${SOURCE_FILES})
- создаем динамическую библиотеку с именем libnumerixppset_target_properties(libnumerixpp PROPERTIES OUTPUT_NAME "numerixpp")
- задаем имя выходного файла на numerixpp (CMake автоматически прибавит префикс lib к названию файла библиотеки)target_include_directories(...)
- добавляем каталог include в качестве общедоступного каталога.foreach(EXAMPLE_SOURCE_FILE ${EXAMPLE_SOURCE_FILES}) ... endforeach()
- перебираем все исходные файлы из директории examples и подключаем к ним библиотекуinstall(...)
- установка библиотеки в системуinstall(DIRECTORY include/
- настраиваем установку заголовочных файлов библиотекиИтак, для сборки надо использовать команду:
Но для облегчения этой задачи напишем простой bash-скрипт:
Не волнуйтесь, весь код мы напишем позже.
В этом разделе я расскажу о системе документирования исходных текстов Doxygen, которая на сегодняшний день, по имеющему основания заявлению разработчиков, стала фактически стандартом для документирования программного обеспечения, написанного на языке C++, а также получила пусть и менее широкое распространение и среди ряда других языков.
Устанавливается Doxygen просто:
Суть автоматизированного софта для генерации документации такая: на вход подаются файлы исходного кода, комментированные особым образом, а на выходе мы получаем структуированный формат документации.
Рассматриваемая система Doxygen как раз и выполняет эту задачу: она позволяет генерировать на основе исходного кода, содержащего комментарии специального вида, красивую и удобную документацию, содержащую в себе ссылки, диаграммы классов, вызовов и т.п. в различных форматах: HTML, LaTeX, CHM, RTF, PostScript, PDF, man-страницы.
В большинстве случаев Doxygen используется для документации программного обеспечения, написанного на языке C++, однако на самом деле данная система поддерживает гораздо большое число других языков: C, Objective-C, C#, PHP, Java, Python, IDL, Fortran, VHDL, Tcl, и частично D.
Итак, сначала нам нужно будет перейти в рабочую директорию и создать Doxyfile - файл конфигурации:
В Doxyfile содержится краткое описание проекта, его версия и подобные вещи. Некоторые значения желательно сразу изменить.
Вот основные значения:
Больше настроек вы можете посмотреть в этой статье.
Дефолтный стиль, мягко говоря, некрасивый. Поэтому мы будем использовать кастомную css-тему:
Данный файл стилей вы можете скачать отсюда.
Посмотреть, что получилось у меня, вы можете по ссылке. А мой Doxyfile здесь.
Документация кода в Doxygen осуществляется при помощи документирующего блока. При этом существует два подхода к его размещению. Он может быть размещен перед или после объявления или определения класса, члена класса, функции, пространства имён и т.д.
Для того, чтобы doxygen правильно создал документацию, стоит следовать стилистике написания комментариев. Рассмотрим пример:
+
- | передаваемый параметр, имеет направление ([in], [out], [in,out]) |
\f$
. Для создания latex-формул можно использовать онлайн редактор latex.Также существуют следующие метки: