Внешние библиотеки
Целевые библиотеки
Аксиома: всё уже написали до нас
- ⇒ Сначала поиск, потом проектирование и исследование, потом разработка
- Ресурсы:
GitHub: хостинг, аналитика, зеркалирование
OpenHub — аналитика
- ресурсы сообществ (дистрибутивов, больших проектов и т. п.)
- ЯП-специфичные хранилища (типа PyPI, NPM, Hackage и т. д.)
- Гугл
Критерии качества:
- Команда и сообщество
- Возраст проекта
- Регулярность разработки
- Качество кода
- Лицензия
- …
Инструментарии (frameworks)
Цели инструментария:
- Кроссплатформенность (возможно, прозрачная!)
- Расширение и переписывание стандартов
- Связное информационное пространство
- Общая идеология разработки
Комфортная среда для DevOps
- ⇒ привлечение сообщества
GLib/GObject
Glib (Си):
- Аналоги типов в Си (числа, ссылки, строки и т. п.)
- в т. ч. надёжная арифметика, атомарные операции
- …
- Списки и двунаправленные списки
- Стеки и очереди
- Словари (ассоциативные массивы, хеш-таблицы)
Строки (человеческие ☺) и кварки (уникальные числовые хеши строк)
- Динамические массивы, косвенные (массивы ссылок), байтовые и т. п.
- Деревья (разные)
- Вариатвные
- Поддержка refcount
- Аналоги типов в Си (числа, ссылки, строки и т. п.)
- На все остальные случаи жизни:
- i18n
- память, куча, динамическая загрузка кода
- процессы, нити, таймеры
- лексический анализатор, синтаксические анализаторы…
- I/O, потоки
- Отладка и диагностика, модульное тестирование
- …
- Свои инструменты тестирования, интернационализации и т. п.
Требует жёсткой дисциплины программирования (все объекты кастятся в gpointer*, проверка типов только руками)
GObject (Си):
- Поддержка ООП на Си
- Классическая динамическая объектная модель
- Классы и экземпляры
- и для класса, и для экземпляра ∃ конструктор, инициализатор, финализатор и деструктор
- Инкапсуляция, наследование, полиморфизм
- Интроспекция и интерфейсы
- Классы и экземпляры
- Поддержка событийного программирования
- Замыкания (более общий вид callbask-ов)
- Сигналы
- Всё программируется на Си с максимально возможной прослойкой макросов, генерирующих недостающие проверки, интерфейсы, структуры и прочее
- Например, различаются наследуемые и ненаследуемые классы (если класс ненаследуемый, нет необходимости работать динамически с его структурой
- Объектная модель очень гибкая, потому что каждый этап эксплуатации класса и его экземпляра надо программировать отдельно
- Требует жёсткой дисциплины программирования
Пример использования GLib
Базовая статья: Manage C data using the GLib collections — учебник Тома Копланда.
Репозиторий с примером разработки простейшей программы с использованием GSList
Пример использования GObject
Базовая серия статей Поперечно-полосатое программирование (Хабр).
есть жуткийрусский перевод более старой версии докуметации (с другим примером)
Минимальный код (спасибо человеку-гипножабе за gist)
1 #include <glib-object.h> 2 3 // Структура, из которой делается класс 4 typedef struct FooBarClass_ { 5 GObjectClass parent_class; 6 } FooBarClass; 7 8 // Структура, из которой делается экземпляр 9 typedef struct FooBar_ { 10 GObject parent; 11 } FooBar; 12 13 // Макро, порождающий набор функций, описывающих класс 14 // FooBar — тип объекта, foo_bar — префикс для этих функций 15 // G_TYPE_OBJECT — родительский класс 16 G_DEFINE_TYPE (FooBar, foo_bar, G_TYPE_OBJECT) 17 18 // Инициализатор класса. Может ничего не делать, но должен быть. 19 static void foo_bar_class_init (FooBarClass *self) { } 20 21 // Инициализатор объекта. Тоже может ничего не делать. 22 static void foo_bar_init (FooBar *self) { } 23 24 int main() { 25 // Создание самого класса с помощью сгенерированной функции 26 GType theClass = foo_bar_get_type(); 27 // Создание экземпляра класса 28 GObject *theObj = g_object_new(foo_bar_get_type(), NULL); 29 // Создание второй ссылки на объект 30 g_object_ref(theObj); 31 // Удаление двух ссылок 32 g_object_unref(theObj); 33 g_object_unref(theObj); 34 // Если раскомментировать ещё один unref, приедет assertion 35 // Это значит, что до этого момента всё работало! 36 //g_object_unref(theObj); 37 }
Более сложный пример
Заголовочный файл cats.h:
1 #ifndef _MYMODULE_CAT_H_ 2 #define _MYMODULE_CAT_H_ 3 #include <glib-object.h> 4 5 // Приезжают вспомогательные макросы 6 G_BEGIN_DECLS 7 8 // Класс Cat будет прописан в пространстве имён (модуле) MYMODULE 9 #define MYMODULE_TYPE_CAT cat_get_type() 10 // Тип Cat, префикс cat, модуль MYMODULE, префикс для модуля CAT 11 // Родительский класс — GObject 12 // От FINAL класса нельзя наследоваться, это сильно упрощает реализацию 13 G_DECLARE_FINAL_TYPE (Cat, cat, MYMODULE, CAT, GObject) 14 15 // struct _CatClass для FINAL_TYPE генерируется автоматически 16 // Структура для экземпляра класса 17 struct _Cat 18 { 19 GObject parent; // Объект родительского класса 20 gchar *Name; // Поле 21 void (*say_meow) (Cat*); // Пола для метода 22 }; 23 24 // Конструктор экземпляра 25 Cat* cat_new(); 26 27 // Функция, которая будет работать методом 28 void cat_say_meow(Cat* self); 29 30 G_END_DECLS 31 32 #endif /* _MYMODULE_CAT_H_ */ 33
Реализация класса cats.c
1 #include <stdio.h> 2 #include <glib.h> 3 #include <glib/gprintf.h> 4 #include "cats.h" 5 6 // Определение класса (порождение функций) 7 G_DEFINE_TYPE (Cat, cat, G_TYPE_OBJECT) 8 9 // Реализация метода 10 void cat_say_meow(Cat* self) 11 { 12 g_printf("%s say: MEOW!\n", self->Name); 13 } 14 15 // Инициализатор класса (посмотрим, когда вызывается) 16 static void cat_class_init(CatClass* self) 17 { 18 printf("Cats invented.\n"); 19 } 20 21 // Инициализатор экземпляра (посмотрим, когда вызывается) 22 static void cat_init(Cat* self) 23 { 24 printf("A cat was born.\n"); 25 } 26 27 // Конструктор экземпляра 28 Cat* cat_new(gchar *Name) 29 { 30 Cat* self; 31 32 self = g_object_new(MYMODULE_TYPE_CAT, NULL); 33 self->Name = Name; 34 self->say_meow = cat_say_meow; 35 return self; 36 }
Использование класса, kitty.c
- Получим:
Другие инструментарии
Универсальных для Си очень мало, и они маложивые
Core_Foundation и его Linux-деривативы
- ???
Для более высокоуровневых языков обкатывают на стророне, а потом забирают в базовый комплект библиотек (как в Python, JS и т. п.) или вообще в стандарт (как с C++)
Инструментарии C++
Цели:
- Тестирование перед включением в стандарт C++
- Best practices, которые не могут быть включены в стандарт (не кросс-платформенные, разрозненные, слишком привязанные к предметной области и т. п.)
Например (я не уверен, что часть этих тем уже не перекочевала в стандарт C++ ☺):
- Алгоритмы
- Поддержка разных компиляторов
- Многопоточное программирование
- Контейнеры
- Модульное тестирование
- Структуры данных
- Функциональные объекты
- Обобщённое программирование
- Графы
- Работа с геометрическими данными
- Ввод/вывод
- Межъязыковая поддержка
- Итераторы
- Математические и числовые алгоритмы
- Работа с памятью
- Синтаксический и лексический разбор
- Метапрограммирование на основе препроцессора
- Метапрограммирование на основе шаблонов
- «Умные указатели»
- Обработка строк и текста
Qt (сайт выглядит как извержение маркетоидного бреда, но на самом деле нет!)
Цели:
- Ускорение/стандартизация разработки
- Создание полного devops-окружения
- Прозрачная кроссплатформенность на C++
Свойства:
- Мета-объекты
- Динамическая объектная модель
- Слоты/сигналы
Множество прикладных модулей
- GUI, мультимедиа и GUI over мультимедиа ☺
- Сеть и Web
- Быстрая разработка приложений на декларативном языке Quick
- БД
- Тестирование
- …
wxWidgets Типичный представитель кроссплатформенного GUI Toolkit, но:
Фишка: для бекенда исопльзуются нативные OS (для Linux — Gtk)
Есть б/м стандартный набор классов общего назначения wxBase
Д/З
Почитать и по возможности отщёлкать Manage C data using the GLib collections — учебник Тома Копланда.
- В любом случае разобраться с Hash Tables — задание про них)
- Написать программу, которая подсчитывает количество вхождений каждого слова из входного текста в этот самый текст, и выводит отсортированную по частоте статистику (второй ключ сортировки не важен)
- Ширина строки текста — не более 80 символов
- понятие «слова» — традиционное: есть символы-«буквы», из которых состоит слово и символы «разделители», последовательности которых стоят между словами. Классификация на ваше усмотрение, лишь бы в строке их находилось несколько и они были разной длины ☺
Использовать как минимум g_hash_table, но лучше ещё
- сортировку (GSlist или GArray)
и вообще обойтись без функций из libc
- Как минимум сделать Make или ninja проект, но можно autotoos / cmake / …
Выложить исходники результата в подкаталог 11_Toolkits отчётного репозитория