Ищете удобный способ вызова Java из C++
Кажется, что большинство документации или вспомогательных библиотек, относящихся к JNI (Java Native Interface), связаны с вызовом собственного кода из Java. Это, по-видимому, основное его использование, хотя оно способно на большее.
Я хочу в основном работать в противоположном направлении: изменить существующую (довольно большую) портативную программу на C++, добавив к ней некоторые библиотеки Java. Например, я хочу, чтобы он вызывал базы данных через JDBC или системы очередей сообщений через JMS, или отправлял электронные письма, или вызывал мой собственные классы Java и т. д. Но с raw JNI это довольно неприятно и подвержено ошибкам.
поэтому я идеально хотел бы написать код C++, который может вызывать классы Java так же легко, как C++/CLI может вызывать классы CLR. Что-то вроде:
using namespace java::util::regex; // namespaces mapped
Pattern p = Pattern.compile("[,s]+");
array<java::lang::String> result =
p.split("one,two, three four , five");
for (int i=0; i < result.length(); i++)
std::cout << result[i] << std::endl;
таким образом, мне не придется вручную выполните работу по получению идентификатора метода, передав имя и странные строки подписи, и будет защищен от ошибок программирования, вызванных непроверенными API для вызова методов. В то это будет выглядеть как эквивалент в Java.
NB. Я ВСЕ ЕЩЕ ГОВОРЮ ОБ ИСПОЛЬЗОВАНИИ JNI! в качестве базовой технологии он идеально подходит для моих нужд. Это "в процессе" и очень эффективно. Я не хочу запускать Java в отдельном процессе и делать вызовы RPC к нему. Сам JNI в порядке. Мне просто нужен приятный интерфейс.
должен быть инструмент генерации кода для создания эквивалентных классов C++, пространств имен, методов и т. д. чтобы точно соответствовать тому, что предоставляется набором классов Java, которые я указываю. Сгенерированные классы C++:
- есть функции-члены, которые принимают аналогично обернутые версии своих параметров, а затем делают необходимое JNI voodoo для вызова.
- оберните возвращаемые значения таким же образом, чтобы я мог естественным образом связывать вызовы.
- поддерживайте статический кэш идентификаторов методов для каждого класса, чтобы не искать их каждый раз.
- быть полностью потокобезопасным, портативный, открытый исходный код.
- автоматически проверять наличие исключений после каждого вызова метода и создавать исключение std C++.
- также работает, когда я пишу собственные методы обычным способом JNI, но мне нужно вызвать другой Java-код.
- массив должен работать полностью последовательно между примитивными типами и классами.
- без сомнения, нужно что - то вроде глобального, чтобы обернуть ссылки, когда им нужно выжить за пределами локальной системы отсчета-снова, должен работать одинаково для всех ссылок на массив / объект.
существует ли такая бесплатная, с открытым исходным кодом, портативная библиотека/инструмент или я мечтаю?
Примечание: я нашел этот существующий вопрос но операция в этом случае не была настолько требовательной к совершенству, как я...
обновление: комментарий о глотке привел меня к этот предыдущий вопрос, что, похоже, указывает на то, что это в основном о противоположном направлении и поэтому не стал бы делать то, что хочу.
важно
- речь идет о возможности писать код C++, который манипулирует классами и объектами Java, а не наоборот (см. заголовок!)
- я уже знаю, что JNI существует (см. вопрос!) Но рукописный код для API JNI излишне многословен, повторяющийся, подвержен ошибкам, не проверяется во время компиляции и т. д. Если вы хотите кэшировать идентификаторы методов и объекты классов, это еще больше многословный. Я хочу автоматически генерировать классы-оболочки C++, которые заботятся обо всем этом для меня.
обновление: я начал работать над собственным решением:
https://github.com/danielearwicker/cppjvm
если это уже существует, пожалуйста, дайте мне знать!
NB. Если вы планируете использовать это в своем собственном проекте, не стесняйтесь, но имейте в виду, что прямо сейчас код несколько часов, и Я только написал три очень unstrenuous тесты до сих пор.
10 ответов
Да, существуют инструменты, которые делают именно это-генерируют оболочки C++ для классов Java. Это делает использование Java API в C++ более прозрачным и приятным, с более низкой стоимостью и риском.
тот, который я использовал больше всего, это JunC++ion. Он зрелый, мощный и стабильный. Первичный автор очень мил и отзывчив. К сожалению, это коммерческий продукт, и дорогой.
Джейс это бесплатный инструмент с открытым исходным кодом с BSD лицензия. Прошло много лет с тех пор, как я последний раз играл с Джейсом. Похоже, там все еще идет активное развитие. (Я все еще помню сообщение USENET оригинального автора, более десяти лет назад, задавая в основном тот же вопрос, который вы задаете.)
Если вам нужно поддерживать обратные вызовы с Java на C++, полезно определить классы C++, реализующие интерфейсы Java. По крайней мере, JunC++ion позволяет передавать такие классы C++ методам Java, которые принимают обратные вызовы. В последний раз, когда я пыталась связаться с Джейсом, так и было. не поддерживаю это-но это было семь лет назад.
Я один из архитекторов prinicpal для продуктов языковой интеграции Codemesh, включая JunC++ion. Мы занимаемся такой интеграцией с 1999 года, и она работает очень хорошо. Самая большая проблема-это не часть JNI. JNI утомителен и труден для отладки, но как только вы получите его правильно, он в основном просто продолжает работать. Время от времени вы нарушаете JVM или обновление ОС, а затем вам нужно настроить свой продукт, но в целом он стабилен.
самая большая проблема заключается в сопоставлении типов систем и компромиссах между общим удобством использования и целевым решением. Например, вам не нравится, что Джейс рассматривает все ссылки на объекты как глобалы. Мы делаем то же самое (с некоторыми аварийными люками), потому что оказывается, что это поведение лучше всего работает для 95% клиентов, даже если это вредит производительности. Если вы собираетесь опубликовать API или продукт, вы должны выбрать значения по умолчанию, которые заставляют работать большинство людей. Сбор локальные ссылки в качестве опции по умолчанию были бы неправильными, потому что все больше и больше людей пишут многопоточные приложения, и многие API Java, которые люди хотят использовать с других языков, внутренне многопоточны с асинхронными обратными вызовами и тому подобное.
мы также узнали, что вы действительно хотите дать людям генератор кода на основе GUI для создания спецификации интеграции. Как только они указали его, вы используете версию CLI для интеграции ее в ночную сборку.
удачи с вашим проектом. Много работы, чтобы все исправить. Мы потратили на это несколько лет, и мы все еще делаем его лучше регулярно.
У меня были почти те же проблемы, в конечном итоге я делал это сам, может быть, это кому-то помогает.
Он имеет небольшой след выполнения ( stringArray; а затем с помощью stringArray[1] - >getBytes() или что-то еще.
повторно вызываем Java С C++.
вы можете делать то, что хотите, но вы должны позволить Java контролировать. Я имею в виду, что вы создаете потоки Java, которые вызывают собственный код, и оттуда они блокируют, ожидая, что ваш собственный код даст ему что-то сделать. Вы создаете столько потоков Java, сколько вам нужно, чтобы получить достаточно работы / throuhput.
таким образом, ваше приложение c++ запускается, оно создает JVM / JavaVM (согласно документированному способу, пример существует в qtjambi кодовая база см. ниже), это, в свою очередь, выполняет обычную инициализацию JNI и систему.loadLibrary () и предоставляет банки с "родной" связью. Затем вы инициализируете кучу потоков и вызываете некоторый код JNI (который вы создали), где они могут блокировать ожидание вашего кода C++, чтобы дать им некоторую работу.
ваш код c++ (предположительно из другого потока) затем настраивается и передает всю информацию, необходимую одному из заблокированных и ожидающих Java Thread workers, затем ему дается приказ запустите, затем он может вернуться в код pure-Java, чтобы выполнить работу и вернуться с результатом.
...
можно настроить и создать и содержать экземпляр JavaVM из кода C++. Это можно принудительно ввести свой собственный путь к классам / банки для настройки содержащейся среды, которую необходимо инкапсулировать в программу C++.
план, который, как я уверен, вы уже нашли на http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html
...
в проекте QtJambi есть своего рода генератор Java JNI C++ = > (над которым я работаю и помогаю поддерживать). Это довольно на заказ для инструментария Qt, но по существу он переводит кучу заголовочных файлов C++ в коллекцию c++ .cpp/.H-файлы и *.java-файл для обеспечения связи и оболочки объекта, чтобы конкурирующая память схемы распределения хорошо сочетаются. Может быть, из этого что-то можно извлечь.
Это, безусловно, доказательство в cencept для того, что вы спрашиваете, генератор просто случайно содержится в проекте qtjambi (но может быть сделан независимым с некоторой работой), и это лицензия LGPL (с открытым исходным кодом). Инструментарий Qt не является небольшим API, но он может генерировать 100 классов для покрытия высокого % API (>85% и почти 100% основных/GUI частей).
HTH
статьи Java Совет 17: интеграция Java с C++ описывает, как это сделать подробно.
У меня также было много трудностей получение JNI для работы на разных операционные системы, справляясь с 32/64-битными архитектурами и убедившись, что правильные общие библиотеки были найдены и загружены. Я обнаружил, что Корба (Мико и Якорб) тоже трудно использовать.
Я не нашел эффективного способа вызова из C / C++ в Java и моих предпочтительных решений в этой ситуации должны запустить мой Java-код как:
автономная программа что я могу легко работать с C / C++ программы с
java -cp myjar.jar org.foo.MyClass
. Думаю, это слишком упрощенно для твоей ситуации.как мини-сервер, принимающий запросы от C / C++ программы на сокете TCP/IP и возврат результатов через этот сокет тоже. Для этого требуется создание сетей и сериализация функций но отделяет процессы C / C++ и Java, и вы можете четко определите любые проблемы как находящиеся на стороне C++ или Java.
Как сервлет в Tomcat и делает HTTP-запросы от мой C / C++ программа (другие контейнеры сервлетов также будут работать). Это также требует написания сетевых и сериализующих функций. Это больше похоже на SOA.
Как насчет использования бережливость или Протокол Буферы для облегчения вызовов Java на C++?
может быть, немного слишком большой молоток для ногтей, но это не то, что описание был построен?
поскольку CORBA, похоже, не то, что вы хотите, вот ссылки, описывающие, как запустить JVM с C/C++ и вызвать JAVA-методы.
http://java.sun.com/docs/books/jni/html/invoke.html и http://java.sys-con.com/node/45840
PS: при взаимодействии Java С C++ вы также должны взглянуть на JNA или bridj.
отвечая на мой собственный вопрос:
не представляется активным проектом. Автор рекомендует не использовать его с JDK 1.5 или более поздней версии.
похоже, у него серьезная проблема: он передает голые указатели своим объектам-оболочкам:
java::lang::Integer* i = new java::lang::Integer("10");
delete i; // don't forget to do this!
это также вызывает более тонкую проблему, которая для представления совместимости назначения (например, класс как подтип интерфейса implements) обертки должны наследовать друг от друга.