Хочу разработать DLL, которая будет подключаться к Java-программе. Нужно понять, что делать с MSVCR. Хочется минимизировать количество артефактов, чтобы для корректной работы хватало самой DLL. Кроме того хочется минимизировать её размер.
JVM собрана с определённой MSVCR. Например версия 8 собрана вроде бы с помощью Visual Studio 2010, т.к. в ней лежит msvcr100.dll. Версия 11 собрана уже какой-то новой VS, там лежит целый ворох api-ms-win-core-console-l1-1-0.dll и тому подобного. Естественно мне так же не хочется зависеть от JVM, т.е. чтобы DLL подключалась к любой JVM.
Также это всё должно работать в Windows XP.
Абсолютно готов писать на чистом C. Даже если буду писать на C++, по сути это будет C со стрелочкой, никаких исключений, никаких STL.
На границе с DLL никакого CRT нет, с этим проблем не должно быть (типа malloc в DLL, free в приложении, такого не будет).
В общем как в итоге всё это правильно организовать? Как я понимаю, у меня есть такие варианты:
1. Использовать статическую линковку. Тогда DLL будет одна, но здоровая.
2. Устанавливать на компьютер VC Redistributable. Не очень удобно, но, похоже, это "правильное" решение.
3. Копировать нужные DLL-ки вместе с моей DLL куда-то (пока не понимаю, куда, достаточно ли будет указать java.library.path или надо прям в JVM их сувать? Не повредит ли это самой JVM, у неё же своя CRT, а ну как всё перемешается).
4. Отключать CRT и писать на чистом WinAPI. В принципе почитал, похоже на хак, но вроде должно заработать? Как я понял, самое геморное это то, что компилятор будет генерировать вызовы некоторых функций и без моего участия, поэтому, возможно, придётся несколько функций скопипастить откуда-то? Вроде не так уж страшно.
В целом мой идеальный вариант: использовать CRT, но при этом использовать как-то ту CRT, которая идёт с JVM (ну взять минимально адекватную версию вроде 2010). Но, как я понял, такого варианта Visual Studio не предоставляет и гарантий совместимости не даёт.
1. Вариант жизнеспособный, но без гарантий. Размер увеличится не сильно, учитывая, что это будет "Си с классами" (линкер выкинет лишнее). Но может сломаться, потому что в CRT есть глобальные переменные, хранящиеся в TLS (per-thread data). И из-за разных версий CRT это может привести к проблемам (плюс, /MT /MD сборки отличаются). В общем, только пробовать и смотреть.
4. Если не пугает жизнь без CRT (или подключение самописной, коих немало), то вполне рабочий вариант. Я бы не назвал это хаком или костылём, для подобной задачи вполне подходят такие методы.
5, который "идеальный вариант":
> Но, как я понял, такого варианта Visual Studio не предоставляет и гарантий совместимости не даёт.
Не предоставляет — придётся цепляться к CRT в рантайме самому (через GetModuleHandle/GetProcAddress для нужных функций либо через delayed import плюс ручной выбор имени нужной DLL). Совместимость остаётся — malloc в 6й студии и в 2019 всё тот же.
Здравствуйте, vsb, Вы писали:
vsb>4. Отключать CRT и писать на чистом WinAPI. В принципе почитал, похоже на хак, но вроде должно заработать? Как я понял, самое геморное это то, что компилятор будет генерировать вызовы некоторых функций и без моего участия, поэтому, возможно, придётся несколько функций скопипастить откуда-то? Вроде не так уж страшно.
Самый правильный вариант, и в нем нет ничего сложного. Да, студия очень любит совать црт везде, но — отключить его вполне реально. Придется только объявить через pragma две функции (или три), memset,memcpy, т.к. объявления вида char a[] = {0}; это memset (почему студия не умеет, как бесплатный PellesC, разрабатываемый одним человеком), заменять это на инлайн асм — вопрос риторический..
Здравствуйте, morgot, Вы писали:
vsb>>4. Отключать CRT и писать на чистом WinAPI. В принципе почитал, похоже на хак, но вроде должно заработать? Как я понял, самое геморное это то, что компилятор будет генерировать вызовы некоторых функций и без моего участия, поэтому, возможно, придётся несколько функций скопипастить откуда-то? Вроде не так уж страшно.
M>Самый правильный вариант, и в нем нет ничего сложного. Да, студия очень любит совать црт везде, но — отключить его вполне реально. Придется только объявить через pragma две функции (или три), memset,memcpy
А где взять хорошие реализации этих функций? Ну т.е. я, конечно, могу их в две строчки написать сам, но, подозреваю, с современными процессорами там всё гораздо сложней, нужны всякие ассемблерные вставки и тд. Есть какой-нибудь авторитетный файлик, откуда их можно выдрать? Или не заморачиваться и написать тупо циклом?
Здравствуйте, vsb, Вы писали:
vsb>А где взять хорошие реализации этих функций? Ну т.е. я, конечно, могу их в две строчки написать сам, но, подозреваю, с современными процессорами там всё гораздо сложней, нужны всякие ассемблерные вставки и тд. Есть какой-нибудь авторитетный файлик, откуда их можно выдрать? Или не заморачиваться и написать тупо циклом?
Так с того же CRT и можно взять. К примеру, вот так
А вообще, смысла нет заморачиваться, не думаю вам несколько тактов процессора сыграют погоду (это же только для объявления переменных, и т.п., типа ZeroMemory).
Тут важно другое — заставить студию подключать именно вашу реализацию, а не с монструозных MSVCRT120.DLL
В общем попробовал, без CRT нужно отключать всякие усиления безопасности, мне это показалось не совсем правильным. Решил средний вариант: линковать статически, но при этом в коде явно не использовать. Добавляет в принципе копейки, около 80 КБ получилась почти пустая DLL-ка.