2011-01-12 3 views
12

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

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

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

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

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

+0

Ваша общая проблема не может быть легко решена; преобразование каждого класса C++ по одному в классы Java через JNI довольно сложно. Почему вы хотите использовать эти классы C++ в Java? Есть ли причина, по которой вы должны использовать Java, но хотите иметь существующую функциональность? – templatetypedef

+0

Я не хочу потерять функциональность моего C++. Он выполняет определенные функции, которые Java не может выполнять сам по себе, и я не знаю, как это сделать на Java. Поэтому я хотел бы интегрировать свой C++ внутри Java. :-) :-) –

+3

«... Он выполняет определенные функции, которые Java не может сделать сам по себе ...» - я бы искренне поставил под сомнение это утверждение. «Не могу»? Доказательства, пожалуйста. – duffymo

ответ

7

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

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

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

+1

У меня есть все готово в моем C++ для сбора мусора из всех частей кода. Я бы чувствовал себя прекрасно для вас, если бы вы могли опубликовать мне минимальный пример использования JNI. :-) –

+0

Вот для чего предназначен учебник в ссылке. – duffymo

+0

Попробуем. Благодаря! –

0

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

Там нет поддерживается способ «обернуть мой C++ код внутри класса Java» (EDIT: Я имею в виду, без JNI ни в коем случае, но JNI является проблематичным.)

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

3

Существует множество учебных пособий для выполнения именно того, что вы хотите сделать. Например, проверьте: 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 (Написать Once, Run Anywhere). Как упомянуто duffymo, также могут возникнуть проблемы с сборщиком мусора, но я думаю, что в последние годы JVM довольно умен в интеграции JNI.

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

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

+0

Ты дал ему классный! Попробуй это в выходные! –

5

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

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

+0

SWIG приятный, если вы хотите написать несколько привязок между несколькими языками. Напишите однократное отображение и просто создайте порты. Но все еще слишком много работы, чтобы переопределить все структуры данных, чтобы отобразить все, даже в SWIG. Это лучше, чем писать JNI. Но есть лучшие альтернативы ala JNA. – chubbsondubs

1

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

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

удачи.

0

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

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

13

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

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

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

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

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

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

В качестве альтернативы вы можете попасть в native signal handling, чтобы уменьшить риски целостности процесса JVM, если вам нравится и придерживаться решения для упаковки.

+0

Спасибо за ваш ответ. Ну, мои архитектурные навыки не очень хорошие. Но я должен написать приложение, как вы упомянули (отделить их от двух процессов), я должен рассмотреть этот совет. Мне потребуется время, чтобы вернуться к вам с небольшим количеством вопросов. Еще раз спасибо.. –

1

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

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

Смежные вопросы