Вызвать методы или функции класса C ++ из Java на андроид без повторного создания класса / переменной при каждом вызове

У меня довольно сложный код NLP, написанный на C ++, и теперь я хочу использовать его в своем приложении для Android. Моя идея заключается в создании приложения с использованием архитектуры клиент-сервер, где клиент является андроидным java-приложением, а сервер – объектно-ориентированным кодом на C ++. Но главная проблема для меня в том, что компоненты C ++ довольно тяжелые (токенизаторы, векторизаторы, данные корпуса и т. Д.), И я не могу их воссоздать при каждом вызове, мне нужно создать их один раз (по первому запросу), а затем Иметь их в памяти, обрабатывать запросы с java-стороны, когда приложение активно.

Не могли бы вы дать мне некоторое руководство, как добиться этого, так как я никогда не использовал C ++ от Android раньше? Заранее спасибо.


Java и C ++-код не удаленный, нет http или других удаленных запросов, это одно и то же приложение. Но чтобы уменьшить количество накладных расходов для обмена между Java / C ++, я не хочу иметь одну точку контакта в Java-коде, например NlpEngine.sendRequest(string textToProcess, int processingWorkflowId) а затем код C ++, основанный на processingWorkflowId идентифицирует, что это Должен делать текст.

Solutions Collecting From Web of "Вызвать методы или функции класса C ++ из Java на андроид без повторного создания класса / переменной при каждом вызове"

Assumtion

Я предполагаю, что у вас есть код C ++, скомпилированный для Android с помощью набора инструментов, такого как Android NDK, и приложение Java на передней панели работает на том же устройстве, что и код C ++ на задней панели.

Частные вызовы Java и состояние сеанса

Независимо от того, какой из трех следующих интерфейсов вы используете. Библиотеки C / C ++ загружаются и остаются в памяти все время, после чего выполняется приложение Java. Состояние библиотеки будет сохраняться все время. Я не понимаю, как вы относитесь к инициализации. Это не похоже на запуск команды в CLI, где другое приложение запускается и останавливается снова и снова.

… Но главная проблема для меня в том, что компоненты C ++ довольно тяжелые (токенизаторы, векторизаторы, данные корпуса и т. Д.), И я не могу их воссоздать при каждом вызове …

Загрузка собственных библиотек в Java

Есть несколько способов загрузки собственных библиотек на Java, я хочу указать три:

  • JNI – собственный интерфейс Java

    JNI – это инструмент, старый, как сама Java. Системные вызовы из SWT были созданы с использованием JNI. JNI – это не простой способ, вы должны определить функции / методы, которые вы хотите сделать в Java как native, скомпилировать их в заголовок C / C ++, написать код для вызова вашей библиотеки в этой промежуточной библиотеке. Скомпилируйте этот код для каждой платформы ABI (в соответствии с NDK есть 7 андроидов ABI ). В программе Java вы найдете платформу для вызова подходящей промежуточной библиотеки ABI. JNI имеет много других подводных камней.

  • JNA – базовый доступ Java

    [JNA] – это java-библиотека, которая динамически загружает библиотеку C / C ++ путем отражения. Определение Java-вызова выполняется в чистом java без дополнительного инструмента. Простота использования имеет компромисс в производительности, накладные расходы на вызов функции до 10 раз медленнее, чем JNI. Но это только играет рулон, если вы очень часто вызываете экстремально короткие функции / методы библиотеки C / C ++. В вашем случае это звучит так, как будто вы просто вызываете несколько раз функции, и эти функции будут занимать там время. JNA используется разработчиками Android.

  • JNR-FFI – Java Rative Runtime

    JNR-FFI является самым новым кандидатом. JNR-FFI – это часть, которую вы используете для вызова библиотек. Другие части являются базовыми для JNR-FFI. Это очень вдохновило JNA. Java-код, разработанный с помощью JNA и с JNR-FFI, выглядит очень похоже. Причина, по которой JNR-FFI была разработана, – это производительность. В целом JNR-FFI немного медленнее, чем JNI (для получения около 15%), но при некоторых обстоятельствах он может быть быстрее, чем JNI. В случае длительной работы на стороне C / C ++ эти накладные расходы не имеют значения. JNR предлагается использовать в Java 9 в качестве стандартной библиотеки JEP 191: интерфейс внешних функций . Предостережения: швы JNR-FFI имеют некоторые проблемы с Android.

Личный опыт

Мне пришлось реализовать некоторые собственные вызовы библиотеки с Java. Я начал с JNI, и после недели тестирования обучения было всего несколько демо-линий, которые работали. Каждая попытка занимала много времени, разные инструменты, длительное время строительства. Чем я нашел презентацию о подводных камнях JNI и какие побочные эффекты пришлось рассмотреть.

Я нашел JNA. В течение нескольких часов первый демо-код с моей библиотекой работал и сравнивался с JNI, он настолько легковес и быстр в разработке. Я перешел на JNR-FFI, потому что это была современная версия JNA. Для того, что я сделал, производительность не была причиной переключения, это был только положительный побочный эффект.

Я не разрабатывал JNA или JNR-FFI под Android. Но в вашем случае я бы попробовал JNA, потому что он лучше поддерживается Android. Я надеюсь, что JNR-FFI внедряется в Java 9, легко переключиться с JNA-кода на JNR-FFI-код.

пример

Я добавил и пример JNR-FFI, чтобы дать вам представление о простоте использования. Больше нечего делать, чем реализовать эти несколько строк, чтобы иметь возможность вызвать собственную функцию c-библиотеки.

JNR-FFI Пример, взятый из Java Rative Runtime – Отсутствующая ссылка Чарльза Оливера Нуттера

 public class GetPidJNRExample { public interface GetPid { @IgnoreError long getpid(); } public static void main( String[] args ) { LibraryLoader<GetPid> loader = FFIProvider .getSystemProvider() .createLibraryLoader(GetPid.class); GetPid getpid = loader.load("c"); getpid.getpid(); } }