Внешние библиотеки
Целевые библиотеки
Аксиома: всё уже написали до нас
- ⇒ Сначала поиск, потом проектирование и исследование, потом разработка
 - Ресурсы: 
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 отчётного репозитория
