JNI DLL и MSVCR
От: vsb Казахстан  
Дата: 12.03.20 14:39
Оценка:
Хочу разработать 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 не предоставляет и гарантий совместимости не даёт.
Отредактировано 12.03.2020 14:40 vsb . Предыдущая версия .
Re: JNI DLL и MSVCR
От: flаt  
Дата: 13.03.20 09:55
Оценка: 12 (1)
1. Вариант жизнеспособный, но без гарантий. Размер увеличится не сильно, учитывая, что это будет "Си с классами" (линкер выкинет лишнее). Но может сломаться, потому что в CRT есть глобальные переменные, хранящиеся в TLS (per-thread data). И из-за разных версий CRT это может привести к проблемам (плюс, /MT /MD сборки отличаются). В общем, только пробовать и смотреть.

4. Если не пугает жизнь без CRT (или подключение самописной, коих немало), то вполне рабочий вариант. Я бы не назвал это хаком или костылём, для подобной задачи вполне подходят такие методы.

5, который "идеальный вариант":

> Но, как я понял, такого варианта Visual Studio не предоставляет и гарантий совместимости не даёт.


Не предоставляет — придётся цепляться к CRT в рантайме самому (через GetModuleHandle/GetProcAddress для нужных функций либо через delayed import плюс ручной выбор имени нужной DLL). Совместимость остаётся — malloc в 6й студии и в 2019 всё тот же.
Re: JNI DLL и MSVCR
От: morgot  
Дата: 13.03.20 13:12
Оценка: 21 (2)
Здравствуйте, vsb, Вы писали:

vsb>4. Отключать CRT и писать на чистом WinAPI. В принципе почитал, похоже на хак, но вроде должно заработать? Как я понял, самое геморное это то, что компилятор будет генерировать вызовы некоторых функций и без моего участия, поэтому, возможно, придётся несколько функций скопипастить откуда-то? Вроде не так уж страшно.


Самый правильный вариант, и в нем нет ничего сложного. Да, студия очень любит совать црт везде, но — отключить его вполне реально. Придется только объявить через pragma две функции (или три), memset,memcpy, т.к. объявления вида char a[] = {0}; это memset (почему студия не умеет, как бесплатный PellesC, разрабатываемый одним человеком), заменять это на инлайн асм — вопрос риторический..

Ну не суть. Еще можно попробовать вот такой хак:
https://m.habrahabr.ru/post/87016/
https://m.habrahabr.ru/post/236355/
https://www.codeproject.com/Articles/15156/Tiny-C-Runtime-Library

Линковать статически — глупо, как и таскать дллки с собой. Если не хотите заморочиться всем вышеперечисленным, то ставьте VC redistributable.

А еще есть хороший вариант. Скачать Pelles C, там есть импорт студийного проекта, и в нем уже закодить как угодно.

Еще можно поставить VC6, она юзает тот CRT, что есть в винде.
Отредактировано 13.03.2020 13:14 morgot . Предыдущая версия .
Re[2]: JNI DLL и MSVCR
От: vsb Казахстан  
Дата: 13.03.20 14:06
Оценка:
Здравствуйте, morgot, Вы писали:

vsb>>4. Отключать CRT и писать на чистом WinAPI. В принципе почитал, похоже на хак, но вроде должно заработать? Как я понял, самое геморное это то, что компилятор будет генерировать вызовы некоторых функций и без моего участия, поэтому, возможно, придётся несколько функций скопипастить откуда-то? Вроде не так уж страшно.


M>Самый правильный вариант, и в нем нет ничего сложного. Да, студия очень любит совать црт везде, но — отключить его вполне реально. Придется только объявить через pragma две функции (или три), memset,memcpy


А где взять хорошие реализации этих функций? Ну т.е. я, конечно, могу их в две строчки написать сам, но, подозреваю, с современными процессорами там всё гораздо сложней, нужны всякие ассемблерные вставки и тд. Есть какой-нибудь авторитетный файлик, откуда их можно выдрать? Или не заморачиваться и написать тупо циклом?
Re[3]: JNI DLL и MSVCR
От: morgot  
Дата: 13.03.20 14:20
Оценка: 12 (1)
Здравствуйте, vsb, Вы писали:

vsb>А где взять хорошие реализации этих функций? Ну т.е. я, конечно, могу их в две строчки написать сам, но, подозреваю, с современными процессорами там всё гораздо сложней, нужны всякие ассемблерные вставки и тд. Есть какой-нибудь авторитетный файлик, откуда их можно выдрать? Или не заморачиваться и написать тупо циклом?


Так с того же CRT и можно взять. К примеру, вот так
#pragma intrinsic(memset)

#pragma function(memset)
void * __cdecl memset(void *pTarget, int value, size_t cbTarget) {
    unsigned char *p = pTarget;
    while (cbTarget-- > 0) {
        *p++ = value;
    }
    return pTarget;
}


А вообще, смысла нет заморачиваться, не думаю вам несколько тактов процессора сыграют погоду (это же только для объявления переменных, и т.п., типа ZeroMemory).
Тут важно другое — заставить студию подключать именно вашу реализацию, а не с монструозных MSVCRT120.DLL
Отредактировано 13.03.2020 14:22 morgot . Предыдущая версия .
Re: JNI DLL и MSVCR
От: vsb Казахстан  
Дата: 15.03.20 10:14
Оценка: +1
В общем попробовал, без CRT нужно отключать всякие усиления безопасности, мне это показалось не совсем правильным. Решил средний вариант: линковать статически, но при этом в коде явно не использовать. Добавляет в принципе копейки, около 80 КБ получилась почти пустая DLL-ка.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.