Обтекание C/С++ внутри Java

Я разрабатываю приложения/программы на C/С++. Я больше разбираюсь в этих двух языках и люблю быть разработчиком на С++. Мне интересно, как создать Java-программу, содержащую весь мой код на С++.

Я имею в виду, я хотел бы обернуть весь мой код на С++ (который уже разработан) внутри класса Java. Но не знаешь, как это сделать.

Пожалуйста, разместите свои ответы или методы/шаги по интеграции С++ внутри Java. (использование JNI - это способ, но я не мог понять это на www, как его использовать)

FYI, я использую Eclipse IDE для разработки.

Как и какие пакеты следует включать в рабочую область проекта?

Ответ 1

Если вы хотите вызвать С++ из Java, вам нужно будет использовать JNI - Java Native Interface.

Будьте предупреждены о том, что вы потеряете некоторые преимущества сборщика мусора, поскольку он не может работать с вашими объектами С++, и ваш код больше не будет переноситься.

Возможно, вам лучше будет учиться писать 100% Java и оставлять С++ позади, но это всего лишь предложение.

Ответ 2

Вместо JNI или JNI с некоторой помощью от автоматического генератора оберток, такого как SWIG или даже JNA, вы можете рассмотреть возможность разделения C/С++ и Java на отдельные процессы и использование какой-либо формы IPC и/или Java Process абстракции для вызова программы, написанной на C/С++. Такой подход отказывается от "обертывания", поэтому в некотором смысле это не ответ на этот вопрос, но, пожалуйста, прочитайте до голосования. Я считаю, что в некоторых случаях это разумный ответ на более широкую проблему.

Причиной такого подхода является то, что при вызове C/С++ непосредственно из Java, JVM подвергается риску любой ошибки в собственном коде. Риск в какой-то степени зависит от того, какая часть собственного кода принадлежит вам и как вы ссылаетесь на сторонний код (и сколько у вас доступа к исходному коду такого стороннего кода).

Я столкнулся с ситуацией, когда мне пришлось вызывать библиотеку C/С++ из Java, а в библиотеке C/С++ были ошибки, которые вызвали сбой JVM. У меня не было исходного кода третьей стороны, поэтому я не смог исправить ошибки в собственном коде. В конечном итоге решение состояло в том, чтобы вызвать отдельную программу C/С++, связанную с третьей стороной библиотеки. Затем приложение Java совершило вызовы многих эфемерных родных процессов всякий раз, когда ему нужно было называть материал C/С++.

Если у нативного кода есть проблема, вы можете восстановить/повторить попытку в Java. Если нативный код завернут и вызван из процесса JVM, он может удалить всю JVM.

Этот подход имеет последствия для производительности и потребления ресурсов и, возможно, не подходит для вашего приложения, но его следует учитывать в определенных ситуациях.

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

В качестве еще одной альтернативы вы можете войти в собственную обработку сигналов, чтобы снизить риски целостности процесса JVM, если вам нравится и придерживаться решения для переноса.

Ответ 3

Вы не можете "просто обернуть его", вам нужно написать некоторый клей C/С++.

Для начала SWIG может выполнять большинство работ для вас.

Ответ 4

Существует множество учебных пособий для выполнения именно того, что вы хотите сделать. Например, проверьте: http://www.javamex.com/tutorials/jni/getting_started.shtml

Существует также много предостережений от использования JNI. Я недавно начал работать с ним (просто для удовольствия, на самом деле), и он имеет тенденцию быть намного менее забавным, чем я ожидал раньше.

Прежде всего, вам нужно иметь дело с загадочным кодом, например:

#include "test_Test.h"

JNIEXPORT jint JNICALL Java_test_Test_getDoubled(JNIEnv *env, jclass clz, jint n) {
    return n * 2;
}

Во-вторых, он имеет тенденцию преуменьшать одну из основных причин, почему вы используете Java в первую очередь: WORA (Write Once, Run Anywhere). Как упомянуто duffymo, также могут возникнуть проблемы с сборщиком мусора, но я думаю, что в последние годы JVM довольно умен в интеграции JNI.

С учетом сказанного, чтобы перенести весь ваш код на С++ в JNI, вам нужно будет реорганизовать свои интерфейсы (и, возможно, даже сделать некоторую внутреннюю гимнастику). Это не невозможно, но это действительно не рекомендуется. Идеальное решение - это просто переписать свой код на Java.

С учетом сказанного вы также можете "конвертировать" ваш код из C/С++ в Java программно, и есть множество таких утилит. Но, конечно, машины глупее, чем люди, и они также обязаны ошибаться, в зависимости от сложности вашего класса.

Ответ 5

Я бы избегал JNI, потому что утомительно писать, многословно и просто боль. Вместо этого я бы использовал библиотеку JNA, которая упрощает запись родной интеграции.

https://github.com/twall/jna/

Удачи.

Ответ 6

Вы можете написать код С++ через JNI, но нет прямого сопоставления классов С++ классам Java. Я использовал JNI для устранения проблем, обнаруженных в SDK android SDK (в частности, невероятно медленной реализации FloatBuffer.put), и я могу использовать его для некоторых критически важных областей. Мой совет будет заключаться в том, чтобы использовать его экономно и в утиной, делать критически важные вещи и уходить, не занимаясь распределением памяти, если вы можете помочь ему. Кроме того, не забудьте измерить свой код, чтобы узнать, действительно ли это происходит быстрее.

Из интереса, на какой платформе вы развиваетесь? Единственной платформой, где было бы целесообразно обернуть много кода С++ на светлом Java-слое, будет Android - на других платформах, просто скомпилировать на С++ и сделать с ним.

Ответ 7

Модуль JNI не является Java-классами. Это C. Использование JNI несет множество ограничений, и некоторые Java-среды не поддерживают JNI.

Нет поддерживаемого способа "обернуть мой код С++ внутри класса Java" (EDIT: я имею в виду, без JNI, но JNI проблематичен.)

Вы можете исследовать собственный компилятор С++, испускающий байт-коды Java, но никто (включите меня) не порекомендует этот подход.

Ответ 8

BridJ был специально разработан для этого (и поддерживается JNAerator, который проанализирует ваши заголовки C/С++ и выплюнет привязки Java для вас).

Это недавняя альтернатива JNA с поддержкой С++.