DLL в играх (с) Дядя Дима

Сегодня вечером на канале прочитал небольшую лекцию про длл. Очень познавательно.

[20:33] [dDIMA] ну вот. Смотри сюда. Нащщет Dll
[20:33] [dDIMA] я начну с самого начала – какого [censored] они вообще появились
[20:33] [dDIMA] были старые добрые винды типа 3.0, 3.1
[20:33] [dDIMA] с общим адресным пространством и все такое
[20:34] [dDIMA] там были dll, которые изобрели, чтобы экономить память – всякие kernel32.dll, user32 и прочие находились в одной копии и юзались всеми программами
[20:35] [dDIMA] потом появилось секьюрное разделение в Win32 extension и позднее – жестко в 95-х
[20:35] [dDIMA] от dll остался только общий код, а данные разошлись
[20:35] [dDIMA] тогдажевдд стали использовать для того, чтобы регистрировать всяческие сервисы, фильтры и т.п. штуки
[20:35] [dDIMA] *тогда же dll
[20:36] [dDIMA] что мы имеем сейчас: dll используются для:
[20:36] [dDIMA] – различных фильтров, кодеков и прочего
[20:36] [dDIMA] – кастомизации обработки в приложениях
[20:36] [dDIMA] начиная от Explorer и заканчивая MS word и прочими Maya
[20:37] [dDIMA] – удобного обновления shared кода независимо от приложений
[20:38] [dDIMA] только третья onerf тоже начинает понемногу уходить, так как теперь есть side by side cache и каждое приложение держит свобю копию необходимых ей dll файлов
[20:38] [dDIMA] все. На этом _разумная_ область применения dll заканчивается
[20:38] [dDIMA] далее начинается _неразумная_ область применения
[20:39] [dDIMA] типа модно разделить проект на несколько частей: engine.dll и game.exe
[20:39] [dDIMA] смысла в таком разделении не то чтобы очень много
[20:40] [dDIMA] 1. фильтры и т.п. – не подходит
[20:40] [dDIMA] 2. кастомизация обработки – не-а
[20:40] [dDIMA] про 2-е – я бы еще поверил, что в dll выносится плагиновая часть игры, но никак не движок
[20:40] [dDIMA] 3. удобное обновление – миф
[20:41] [dDIMA] если тебе удастся сделать engine.dll, который не будет меняться хотя пару лет – я немедленно [censored]
[20:41] [dDIMA] *хотя бы
[20:41] [dDIMA] все равно обновляться всегда будет движок и игра одновременно – чудес на свете не бывает
[20:41] [dDIMA] поэтому такое разделение – оно во многом искуственно
[20:44] [dDIMA] Итак, что мы получаем, разделив exe на 2 части:
[20:44] [dDIMA] 1. Разные heaps
[20:44] [dDIMA] аллокации в dll и деаллокации этой памяти в основной программе могут привести к падению
[20:45] [dDIMA] то есть надо жесткое разделение – никогда конструктор и деструктор не должны вызываться из разных модулей
[20:46] [DrPadawan] или менеджер памяти
[20:46] [dDIMA] теоретически это может быть даже разумным – типа если есть CreateObj(), то для него delete вызывать нельзя, а надо писатьметод DestroyObj(), который сделает delete this, но опязательно в source файле
[20:46] [dDIMA] Да, или извращаться со своим менеджером памяти
[20:46] [dDIMA] Сниму шляпу, если вы сделаете быстрее и эффективнее виндов 🙂
[20:46] [dDIMA] 2. Жесткие ограничения на интерфейсы
[20:47] [dDIMA] глобальными переменными так просто уже не воспользоваться, все на интерфейсахи т.п.
[20:48] [dDIMA] Был проект ***. Там количество классов можно было смело уменьшить вдвое, потому что для каждого класса писался ICamera, IConsole и т.п.
[20:48] [dDIMA] Странно , что у них не было IVector3 🙂
[20:48] [DrPadawan] dDIMA в смысле “для каждого класса писался ICamera, IConsole ”
[20:48] [dDIMA] ага
[20:48] [DrPadawan] это для каких классов?
[20:49] [dDIMA] и выносился в отдельную dll с поиском по GUID 🙂
[20:49] [DrPadawan] т.е. на каждый чих – интерфейс
[20:49] [dDIMA] да
[20:49] [DrPadawan] ну это паталогия
[20:49] [dDIMA] и все таки
[20:49] [dDIMA] 3. необходимость жестко следить на одинаковыми настройками компиляции, соответствием exe и dll в процессе разработки и т.п.
[20:50] [dDIMA] По хорошему, при отладке вам не удастся разделить работу так, чтобы один собирал только dll, а второй – exe
[20:50] [dDIMA] потому что при первом же чихе когда программа упадет в отладчик в dll (или в exe) – если у вас нет пересобранной версии, MSCV ничего кроме дизасма вам не покажет
[20:51] * DrPadawan думал, что главное при этом pdb файлы
[20:51] [DrPadawan] вроде всегда показывало
[20:52] [dDIMA] если ты поменял header, который включается в непересобранную dll, у тебя будет мисматч
[20:52] [dDIMA] с соответствующими вытекающими
[20:52] [DrPadawan] будет
[20:52] [DrPadawan] ну да, сразу тогда придется всё пересобирать
[20:53] [dDIMA] то есть все равно надо держать на локалке и пересобирать всегда весь проект
[20:53] [DrPadawan] или плодить интерфейсы
[20:53] [dDIMA] нет, я говорю про удобство отладки
[20:53] [dDIMA] Ну и 4, уже мелкозаметное – это лишний jmp на вызовах в Dll
[20:54] [dDIMA] теперь о плюсах
[20:54] [dDIMA] 1. Вынужденное четкое разделение на компоненты, которые связаны только функциональными вызовами
[20:55] [dDIMA] 2. меньшее время линковки отдельных dll. Может быть большим плюсом при активном использовании STL и Boost, когда все symbol table не помещаются в linker cache
[20:55] [dDIMA] да, но при этом время checking dependencies и загрузки приложения несколько увеличиваются
[20:56] [dDIMA] а, еще из нюансов dll – существенное усложнение отладки по базовым креш-дампам (см. мою статью на DTF)
[20:56] [dDIMA] короче, мое резюме такое: применение dll в игровом проекте – это притягивание технологии за уши
[20:57] [dDIMA] в редакторах для подключения плагинов, для выноса общей функциональоности в рамках нескольких проектов – на здоровье
[20:57] [dDIMA] но на ровном месте писать main() в главной exe, а func() помещать в dll – просто ничем не обосновано