Использование Java для переноса поверх C ++ - PullRequest
11 голосов
/ 28 июля 2010

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

  1. Какие инструменты я могу использовать для достижения этой упаковки.
  2. Какую часть кода C ++ я должен был бы изменить, если таковой имеется.
  3. Любые другие идеи / вопросы, которые у вас возникнут.

Спасибо.

Ответы [ 6 ]

7 голосов
/ 29 июля 2010

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

http://www.swig.org/

Javaклассы, сгенерированные SWIG, имеют идентичные интерфейсы с классами C ++, которые они обертывают, что означает, что взаимодействие с объектами C ++ из Java предполагает только работу с объектами Java.

Вот пример:

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

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();
}

Вызов объектов C ++ из Java аналогичен написанию обычной Java:

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

Строка 1: создается экземпляр Java-оболочки SomeClass, а также объект C ++ типа SomeClass.

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

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

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

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

interface.i: {#include "ClassDefinition.h"}% include "ClassDefinition.h"

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

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

5 голосов
/ 28 июля 2010

JNI

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

ЮНА

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

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

  • JACOB: COM-мост Java (Windows)
  • ...
3 голосов
/ 28 июля 2010

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

2 голосов
/ 28 июля 2010

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

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

1 голос
/ 29 июля 2010

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

Я недавно работал над проектом, в котором у нас была библиотека, распространяемая третья сторона, которая была написана на C ++. Но каждая система, у нас есть это Возможно, эта библиотека была написана на Java.

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

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

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

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

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

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

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

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

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

0 голосов
/ 28 июля 2010

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

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

...