Использование Java для переноса поверх С++

У меня есть проект, написанный на С++, и я хочу написать графический интерфейс Java в качестве интерфейса к нему. Выбор Java исправлен, поэтому мне нужно узнать, как можно называть код на С++ с Java. Переписывание кода С++ не является вариантом. Я хотел бы ввести:

  • Какие инструменты я могу использовать для достижения этой упаковки.
  • Сколько кода на С++ я должен обязательно изменить, если таковой имеется.
  • Любые другие идеи/последующие вопросы, которые у вас были бы.

Спасибо.

Ответ 1

Вы должны искать JNI - собственный интерфейс Java

Ответ 2

Недавно я работал над проектом, в котором мы должны были делать то же самое. У нас была модель данных, написанная на С++, и нам нужно было поместить графический интерфейс Java сверху. В результате мы определили классы С++, которые нам нужны для доступа из GUI, и использовали SWIG для создания простых старых классов Java, которые завернули объекты С++.

http://www.swig.org/

Классы Java, созданные SWIG, имеют одинаковые интерфейсы с классами С++, которые они обертывают, что означает, что связь с объектами С++ из Java связана только с работой с объектами Java.

Вот пример:

Для двух классов С++:

class SomeClass {
public:
  void foo(SomeOtherClass bar);
  SomeOtherClass baz();
}

class SomeOtherClass {
public:
  void do();
}

SWIG создаст два класса Java:

public class SomeClass {
  public void foo(SomeOtherClass bar);
  public SomeOtherClass baz();
}

public class SomeOtherClass {
  public void do();
}

Вызов объектов С++ из Java, подобно написанию регулярной Java:

SomeClass sc = new SomeClass();
SomeOtherClass soc = sc.baz();
sc.foo(soc);

Строка 1: Создана оболочка Java SomeClass, а также объект С++ типа SomeClass.

Строка 2: Вызовы к экземпляру sc SomeClass перенаправляются на экземпляр С++ SomeClass. Возвращаемое значение экземпляра С++ передается в оболочку Java и возвращается оболочкой Java.

Строка 3: SWIG обрабатывает преобразование из типов оболочки Java (или примитивных типов java) в базовые типы С++.

SWIG позаботится о преобразовании в/из типов Java/С++ во время вызова метода и все детали JNI будут скрыты от вида:)

Код интерфейса SWIG, необходимый для создания оболочки Java для класса С++, может быть таким же простым, как:

interface.i:   {   #include "ClassDefinition.h"   }   % включают "ClassDefinition.h"

SWIG очень мощный. Все, что вам нужно сделать, вы можете сделать либо с основными функциями, типами, картами типа джавакода, либо с директорами.

SWIG также позволяет вашему С++-коду вызывать ваши объекты Java без каких-либо изменений в вашем существующем коде С++. Это функция, называемая "кросс-языковой полиморфизм". кросс-языковой полиморфизм, по существу, позволяет создавать классы Java, которые подклассы С++-классов. Затем вы можете передавать экземпляры этих классов Java в качестве параметров для вызовов методов С++. Любые вызовы из С++ в переданном экземпляре будут перенаправлены обратно на ваш объект Java. Я не буду вдаваться в подробности здесь, но это не очень сложно, как только вы преодолеете первоначальный шок этой идеи.

Ответ 3

JNI

  • Если ваш код С++
  • JNI является частью среды java
  • объявить собственные функции и сгенерировать заголовок c/С++ с помощью javah
  • напишите код c/С++, чтобы приклеить ваш код к java-методам.

ЮНА

  • Если у вас есть c api для вашего кода
  • не работает с классами С++
  • JNA не является частью среды java, jna.jar - 300 КБ
  • объявить java-интерфейс с помощью методов c, которые вы используете
  • напишите java-код, чтобы приклеить вашу dll к java
  • необходимо создать java-копию c-структур, используемых функциями dll

Оба они независимы от платформы. Я предпочитаю jna сам, так как легко перепутать jni-код. Есть также несколько зависимых от платформы решений, но я не очень хорошо их знаю.

  • JACOB: java COM-мост (окна)
  • ...

Ответ 4

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

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

Ответ 5

Я бы пошел на какую-то форму IPC (трубы, может быть, даже сокеты). Таким образом, ваш код сводится к копированию в и из массивов байтов на С++, и использование InputStreams и OutputStreams в Java.

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

Мы поехали по пути обертывания библиотеки как родной исполняемый файл, который читает ввод от stdin, переводя его на вызовы функций на библиотека. Соответственно, результаты из библиотеки были преобразованы и напечатан на стандартный вывод.

Это также означало, что обертка была легко проверена, поскольку все, что мне нужно было сделать был вызван в командной строке. Пытался много ошибок и проблем из-за этого. Тщательно порекомендуйте его.

Следующая проблема: "Как вызвать оболочку С++" и "Как сделать упаковать его с помощью приложения Java? Мы фактически избегали ответов на эти вопросов, выставляя исполняемый файл через inetd. Итак, наша java приложения вызывают код C, открывая сокет. Потому что я закодировал обертка для связи через stdout и stdin, мне не пришлось изменять он вообще может разоблачить его через TCP (прочитайте inetd, если вы озадачены). Самый простой способ программирования, который я когда-либо делал...: -)

Жаль, что я пошел по тангенту там. Я пытался проиллюстрировать гибкость, которую вы можете получить, если решите разделить код на С++ на отдельный процесс. Дело в том, что вы сделали работу по сортировке ваши структуры данных впереди. Поэтому изначально вы можете сохранить свою обрабатывать локально и связываться с ним через трубу. Дело в том, что если вы когда вы решите, что вам нужно отправить запросы на удаленный TCP-сервер, это не потребует больших усилий для изменения java-программы. Вы имеете уже выполнил основную часть работы. Это может быть целесообразно рассмотреть. Является ли это действительно подходящим для вас, я не знаю.

Я не кодировал JNI, но у нас есть приложения, которые используют его на работе, и все они страдают от проблем с управлением памятью:

1) Если код C/С++ совершает ошибку с арифметикой указателя, ваша Java приложение также завинчивается. Вероятно, он умрет вместе с SIGSEGV. Так что ваши Код C/С++ лучше быть прочным, проверенным и заслуживающим доверия. С проект, над которым я работал, большинство приложений Java были серверными процессами, которые должны работать 24/7. Мы не доверяли этой третьей стороне библиотека, которая очень полезна, как может быть.

2) Передача структур данных между Java и С++ может быть проблематичной. Особенно, если вы передаете объекты Java в функции C. Вы обычно должны выполнить какое-то преобразование, что вызывает такие проблемы, как "Я должен скопировать эту структуру данных? Когда я должен его уничтожить? Это особенно плохо, если вы случайно называете "свободным" на каком-либо объекте, который был выделенных в программе Java.

3) Я видел некоторый код JNI. Это просто выглядит уродливо... [barf]

Извините за длинный пост.

Ответ 6

Скомпилируйте GUI с помощью GCJ и используйте CNI для переноса кода на С++. См. http://gcc.gnu.org/java/faq.html#6_2 для некоторых сравнительных примеров использования CNI в сравнении с JNI (что вы бы использовали со всеми другими исполняемыми процессами Java).

Предполагается, что CNI намного проще, чем JNI.