Подтвердить что ты не робот

Как создать версию Agnostic DLL для среды выполнения на С++?

Мой продукт - это библиотека С++, которая в Windows распространяется как dll. Это очень мало использует c-runtime (базовый iostream и его), поэтому я уверен, что все последние версии CRT будут в порядке.

Поскольку мой клиент должен создавать свое приложение с помощью моей dll, я не хочу навязывать ему какую-либо конкретную версию. Я бы хотел, чтобы моя dll привязывалась к любой версии библиотеки времени исполнения, используемой моим клиентским приложением (и я могу предположить, что он будет использовать динамическое связывание для своего CRT). В конце концов, разве это не динамическая связь? Возможно ли это?

EDIT: привязка dll к статическим исполняемым файлам не будет работать, потому что тогда статическая среда выполнения (из dll) и динамическая среда выполнения (из клиентского приложения) будут смешаны, что плохо.

EDIT: то, что я в основном задаю, - это как сказать загрузчику времени выполнения, чтобы связать мою dll с любым CRT, с которым связано приложение? Может, что-то с манифестом? В более общем плане, мой вопрос заключается в том, как создать красивую dll, которая будет использоваться клиентами, создающими их собственные приложения?

EDIT: благодаря советам в ответах я передал все ссылки на классы std на встроенные функции в своих заголовках и связал свою DLL со статическими библиотеками времени исполнения. Теперь он работает даже в приложениях, связанных с различными версиями CRT.

4b9b3361

Ответ 1

Нет никакого реального способа гарантировать, что ваша DLL работает с несколькими режимами работы - любой из типов, которые меняются между ними, может привести к несовместимости. Например, размер объекта может измениться или местоположение членов в них. В С++ очень мало места для такого рода вещей.

Лучшее, что вы можете сделать, это статически связать с временем выполнения и обеспечить, чтобы экспортированный API был ограничен типами строго под вашим контролем - без передачи std::string функции, без stdlib-типов в качестве элементов и не new в одной DLL и delete в другой. Не смешивайте встроенные и экспортированные функции (включая конструкторы/деструкторы) для одного и того же объекта, потому что порядок членов и дополнение могут меняться между компиляторами. Идиома pimpl может помочь здесь.

Ответ 2

Если вы открываете любые объекты С++ через границы DLL, это просто невозможно. Что вы можете сделать (и мы используем стороннюю DLL, которая это делает) - это сборка вашей библиотеки в нескольких конфигурациях (32-разрядная/64-разрядная, debug/release, статическая/динамическая среда выполнения, статическая/динамическая библиотека), чтобы удовлетворить как можно больше людей. Это может быть немного утомительно для настройки вначале, но как только вы настроите все настройки, это просто вопрос их построения. Конечно, вам также нужно подумать о том, в какой среде вы создаете против (vc8, vc9, vc10 и т.д.), Поэтому, если вы хотите охватить все базы, у вас может быть довольно много конфигураций.

Ответ 3

Связывание вашей DLL с статической исполняемой средой должно работать, за исключением того, что вы должны быть очень осторожны в управлении памятью (например, любой, кто называет вашу DLL, не может освобождать() или удалять [] все, что было выделено вашей DLL), и вы не можете обменять стандартных структур данных C (например, FILE *). (Я ничего не пропустил?)

Ответ 4

Вы можете добиться этого, используя вызовы WinAPI для ввода-вывода и всего остального, которые, возможно, зависят от среды выполнения.

Наиболее болезненной является то, что вам может потребоваться переопределить глобальные new и delete, чтобы использовать функции WinAPI исключительно потому, что они, вероятно, будут использовать malloc/free внутри. Есть много других болезненных аспектов этого, и мое мнение состоит в том, что это не стоит проблем. Здесь - статья, посвященная этой теме.

Ответ 5

Если вы хотите подвергать объекты объекту в нейтральном режиме, тогда я не вижу никакого решения, кроме COM.

Ответ 6

Ну, есть огромная разница между C-runtime и С++ - runtime. Если вы где использовать msvcrt.dll, который в последние годы стал "рыцарем" как подлинной системной DLL, вы могли бы полагаться на его существование на XP вперед (хотя для Windows 2000 вам понадобится некоторое распространение для версии 6 файла msvcrt.dll). Вы можете использовать msvcrt.dll, компилируя свой код с помощью компилятора из последних WDK (комплектов драйверов Windows). Хотя это код пользовательского режима, это жизнеспособный и хороший способ его компиляции.

IOStreams, однако, требуют С++ - runtime. И это усложняет ситуацию.

EDIT: привязка dll к статические исполняемые файлы lib тоже не будут работать, потому что тогда статическое время выполнения (из dll) и динамическое время выполнения (от клиентское приложение) будет смешанный, что плохо.

Хорошо, если вы смешаете код таким образом, у вас что-то не так в вашем дизайне. У вас возникли бы аналогичные проблемы при запуске отладочной сборки вашей DLL с выпуском другого кода или наоборот.

Я могу только рекомендовать вам либо напрямую использовать COM, либо - если это слишком большой - попытайтесь подражать некоторым идеям COM. Самое главное, что у вас есть функция factory и что (класс) объявлен (и не изменяется) между этими двумя фрагментами кода (т.е. DLL и его вызывающим). Функция factory возвращает экземпляр класса, и класс будет управлять своим временем жизни (что подразумевает, что весь код для распределения и освобождения будет находиться в одном и том же объекте, т.е. Вашей DLL). Управление жизненным циклом затем будет отображаться с помощью функций-членов addref и release. IUnknown может быть основой для вашего интерфейса, не полагаясь на другие части реального COM.

РЕДАКТИРОВАТЬ: Я в основном спрашиваю, как это сделать Я говорю загрузчику времени выполнения, чтобы связать мой dll против любой CRT приложение связано с? Что нибудь с манифестом, возможно? Больше Как правило, мой вопрос заключается в том, как построить хорошо продуманная DLL, которая должна быть используемые клиентами, они сами приложения?

Нелегко. Даже если у вас установлены все версии VS, вам придется script выйти из этой дилеммы, чтобы выбрать правильную версию.

Ответ 7

Ваша dll связана с c-runtime, с которой она была скомпилирована. Ваше приложение всегда будет использовать это время выполнения. Любой, кто ссылается на вашу dll, использует c-runtime. Таким образом, с этим не будет никаких проблем.

Ответ 8

Если вы используете С++, кажется невозможным пересечь границы времени выполнения, если вы не ограничиваете себя тем, что может быть выставлено. Как упоминалось ранее, std:: objects не работают (например, std::string).

Вот небольшой пример, который приведет к сбою:

класс Base  {
 общественности:
   virtual ~ Base()
   {
   }
 };

class ClassInDll: public Base
{ общественности:  __declspec (dllexport) ClassInDll (int arg);
 __declspec (dllexport) ~ ClassInDll();

частные:   int _arg,
};

Если этот класс скомпилирован в DLL-версию режима выпуска VS2008, а один из них создает файл .exe в режиме отладки VS2008, выполните следующие действия:

ClassInDll * c = new ClassInDll (1); delete c;

оператор "delete c" вызывает сбой. Это связано с тем, что ClassInDll имеет виртуальный деструктор.