winapi — Расширения оболочки: статическое связывание или динамическое связывание динамических библиотек C / C ++

При сборке Windows Explorer расширения оболочки (в настоящее время используется VS2010 SP1), вы предлагаете статическое связывание (в CRT, C ++ и другие библиотеки поддержки, такие как ATL) или динамическое связывание?

Одно из преимуществ статическое связывание вариант сделать развертывание проще (на самом деле, таким образом, можно просто развернуть DLL-библиотеку COM-сервера расширения оболочки без внешних зависимостей от других C / C ++ исполняемых DLL).

В случае динамическое связывание, если msvcr100.dll, msvcp100.dllи др. DLL в Windows\System32 используются расширением оболочки, и хорошо, что если Microsoft что-то исправляет (например, исправления безопасности) в этих DLL, исправления автоматически используется пользовательским расширением оболочки.
Тем не менее, плохо то, что эти «глобальные» исправления могут также вносить ошибки и перерыв вещи в зависимом коде.

Что касается приложение-местный развертывание VCRedist DLLs, я не уверен, как это может работать в случае расширения оболочки. Какой тип манифеста должен быть встроен в COM DLL расширения оболочки, чтобы ссылаться на библиотеки VCRedist в папке расширения оболочки?

1

Решение

Необходимость использования DLL-версии CRT обычно является довольно сложным требованием, когда несколько модулей взаимодействуют друг с другом. Одним из особенно важных аспектов является использование одного и того же распределителя во всех модулях. Таким образом, объект, который был размещен в одном модуле, может быть безопасно уничтожен кодом в другом модуле. Это часто встречается в C ++, делать что-то столь же простое, как возвращение std :: string из функции, очень хлопотно. Он создается в вызываемой и должен быть уничтожен в вызывающей. Бедствие происходит, если вызов функции был выполнен за пределами модуля, и два модуля используют разные кучи.

Расположение стандартных объектов C ++ также связано с реализацией CRT. Разные версии компиляторов используют разные реализации std :: string. Бедствие происходит, если один модуль использует реализацию, отличную от другого, вызывающий просто не может правильно использовать объект, созданный вызываемым. Даже такая простая вещь, как настройки отладки, может привести к несоответствию, поддержка отладки итератора в Microsoft CRT особенно печально известна тем, что вызывает несоответствие, она делает объект STL больше.

Это, однако, проблемы, которых избегают в COM. Существует надежный протокол управления памятью, основанный на методах AddRef и Release интерфейса IUnknown. Который держит создателя объекта всегда владельцем объекта и несет ответственность за его уничтожение. Другие распределения, такие как BSTR и SAFEARRAY, всегда должны выполняться из кучи, которая гарантированно будет использоваться в процессе. CoTaskMemAlloc, CoTaskMemFree и IMalloc реализуют эту систему.

И это решительно избегает проблемы размещения объектов, COM строго работает только с интерфейсами. Делать что-то вроде передачи объектов C ++ или исключений через границы взаимодействия строго запрещено. Единственными деталями реализации являются соглашение о вызовах, строго __stdcall, и макет v-таблицы интерфейса, строго привязанный к IID интерфейса. Изменение интерфейса требует выбора нового IID.

Короче говоря, вам вообще не нужно использовать совместно используемую версию CRT. И на самом деле многие COM-серверы скомпилированы с / MT. Использование / MD также хорошо, вы должны учитывать это, только если ваш COM-сервер реализован с использованием нескольких модулей.

2

Другие решения

Краткий ответ на этот вопрос — «это зависит». Но это, вероятно, как далеко вы уже получили.

Тем не менее, это действительно становится выбором «меньшее из двух зол», и в значительной степени это зависит от того, что делает ваше расширение. Если вы строите его статичным, насколько он велик по сравнению с нестатичным? Если нет большой разницы, то вы, очевидно, не используете огромное количество кода DLL в любом случае, что было бы хорошо.

Если вы обнаружите, что ваше расширение увеличивается с нескольких десятков килобайт до нескольких мегабайт, то вам нужно подумать, лучше ли попросить клиентов загрузить redist-пакет или включить его как часть вашей установки.

Не существует единственного правильного ответа. Это компромисс, и вы должны судить, что для вас (и ваших клиентов) наиболее целесообразно — простая установка или зависимость от внешних DLL.

Если вы устанавливаете Redist DLL в той же папке, что и исполняемый файл, Windows найдет там DLL самостоятельно, поэтому не требует дополнительной работы. (Не применимо для расширений оболочки)

2

По вопросам рекламы [email protected]