Обертывание библиотеки Java с C++ (JNI)
У меня есть большая программа, написанная на C++, которая должна использовать определенную библиотеку Java. В идеале я хотел бы создать эквивалентную библиотеку C++, которая обернет этот существующий код Java. Поэтому я изучал API вызова JNI.
Поскольку я не очень опытный программист, и у меня также нет опыта работы с JNI и многоязычным программированием, я был бы очень признателен за некоторые общие советы / подсказки / советы относительно того, как решать эту проблему.
Вещи, которые мне было бы особенно интересно узнать:
- Должен ли каждый класс Java в библиотеке Java отображаться на связанный класс C++? Т.е. в моей библиотеке C++ будет ли класс, каждый из которых вызывает JVM для определенного класса Java? Или у меня будет единственная JVM, через которую все получают доступ? Каков наилучший способ сделать это и почему?
- Каков будет основной процесс и архитектура для этого?
- Существуют ли какие-либо конкретные ресурсы для создания библиотеки C++ из библиотеки Java с использованием API вызова?
Большое спасибо!
1 ответ
Я делал это раньше, но это не для слабонервных, особенно если ваш интерфейс между двумя языками сложен. Отладка также может быть болью в этой ситуации.
Чтобы ответить на ваши вопросы:
Вы должны начать с определения того, какие функции из библиотеки Java вам нужны для доступа в вашей программе на C++. Это всего лишь несколько задач? Попробуйте сделать очень простой интерфейс от C++ до Java в этом случае. Это сложно? Затем вам нужно начать отображать Java-классы на C++, и чем больше вам нужно, тем больше будет работы.
Конец q1 - это действительно Сорта q2. Ваша программа на C++ запустит одну JVM, которая будет работать как часть вашей программы. Когда вы выполняете вызовы через C++, данные будут переданы в JVM, затем будет выполнен код Java, а затем возвращенные значения переданы обратно. Это влечет за собой затраты производительности, поэтому вызов небольших функций, таких как
add(int,int)
через JNI было бы дороже, чем просто делать это в C++.Есть много основных руководств, которые вы можете использовать в Google, чтобы начать. Простое управление запуском базовой JVM из C++ и выполнение вызова на самом деле немного трудоемкие, поскольку вам нужно правильно определить пути к библиотекам JVM, или это не работает (если они не улучшили это, прошло много лет с тех пор, как я пытался). Поэтому вы можете сначала проверить это, прежде чем задавать более конкретные вопросы о JNI и функциях отображения.
Альтернативный вариант (который может или не может быть невозможным в зависимости от вашей библиотеки и варианта использования) - просто написать какой-нибудь сервис-оболочку вокруг вашей библиотеки, фактически на Java. А затем отправляйте запросы к нему через JSON-HTTP или какую-либо систему обмена сообщениями.
Еще более альтернативный вариант, переписать все, что библиотека делает в C++.
Вы можете использовать библиотеку scapix:: link:: java C++ JNI для генерации заголовков C++ для любого кода Java, а затем легко получить доступ к этому коду Java из C++. Вот пример:
#include <scapix/java_api/java/lang/System.h>
#include <scapix/java_api/java/util/Locale.h>
#include <scapix/java_api/java/text/DateFormatSymbols.h>
using namespace scapix::link::java;
using namespace scapix::java_api;
void test1()
{
// C++ objects are automatically converted to and from corresponding Java types.
// This works for any type supported by scapix::link::java::convert() interface,
// which supports many STL types and can be extended for your own types.
std::string version = java::lang::System::getProperty("java.version");
std::vector<std::string> languages = java::util::Locale::getISOLanguages();
std::vector<std::vector<std::string>> zone_strings = java::text::DateFormatSymbols::getInstance()->getZoneStrings();
std::map<std::string, std::string> properties = java::lang::System::getProperties();
}