Встраивать Java в приложение C ++? - PullRequest
19 голосов
/ 22 сентября 2011

Я получил приложение, написанное на C ++, и я могу расширить функциональность приложений, написав для него плагины на C ++.

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

Я читал кое-что о JNI, но всегда есть речь из полной программы, использующей классы Java.

Что бы якак это делать, это использовать классы из C ++ в Java для взаимодействия с приложением.
В данном случае это 3D-приложение, которое называется Cinema 4D.

Есть ли способ компилировать и оценивать код Java приприложение работает (на каком-то языке сценариев) с использованием JNI или чего-то подобного?

Пример мнимого кода после выполнения встраивания:

import c4d.documents.*;

class Main {
  public static void main() {
    BaseDocument doc = GetActiveDocument();
    BaseObject op = doc.GetActiveObject();
    if (op != null) {
      op.Remove();
    }
  }
}

Этот код должен взаимодействовать с Cinema 4D для удаления выбранного объекта.

Ответы [ 6 ]

41 голосов
/ 22 сентября 2011

Вы можете встроить JVM в свое приложение.В официальном справочнике Oracle есть некоторые подробности.Вот краткий обзор:

#include <jni.h>       /* where everything is defined */

int main() {
  JavaVM *jvm;       /* denotes a Java VM */
  JNIEnv *env;       /* pointer to native method interface */
  JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
  vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
  /* Get the default initialization arguments and set the class 
   * path */
  JNI_GetDefaultJavaVMInitArgs(&vm_args);
  vm_args.classpath = ...;
  /* load and initialize a Java VM, return a JNI interface 
   * pointer in env */
  JNI_CreateJavaVM(&jvm, &env, &vm_args);
  /* invoke the Main.test method using the JNI */
  jclass cls = env->FindClass("Main");
  jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
  env->CallStaticVoidMethod(cls, mid, 100);
  /* We could have created an Object and called methods on it instead */
  /* We are done. */
  jvm->DestroyJavaVM();
}

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

3 голосов
/ 22 сентября 2011

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

  1. Для встраивания Java в приложение C ++ вы можете сделать вызов сокета для программы Java. На стороне Java вы используете SocketServer, а на стороне C ++ - библиотеку General Socket Layer. Это, безусловно, самый простой и масштабируемый подход. Поскольку ваша рабочая нагрузка на Java продолжает расти, вы продолжаете добавлять дополнительные jvm. Немного сложен в развертывании, но работает очень хорошо.

  2. Для встраивания приложения C ++ в Java. Это просто Вы компилируете приложение C ++ в общую библиотеку и используете JNI для его вызова.

2 голосов
/ 22 сентября 2011

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

API вызова JNI поддерживает это, как описано @awoodland. Вот текущая ссылка для Java 6/7 .

Что я хотел бы сделать, так это использовать классы из C ++ в Java для взаимодействия с приложением. В данном случае это 3D-приложение, которое называется Cinema 4D.

Для этого вы можете использовать одно из следующих:

  • Собственные методы Java, реализованные в C
  • ЮНА
  • SWIG

Есть ли способ компилировать и оценивать код Java, пока приложение выполняется (на каком-то языке сценариев) с использованием JNI или чего-либо еще нравится?

BeanShell или Groovy , помимо прочего, могут представлять интерес для вас. Оба поддерживают динамически интерпретируемый код, который выполняется на JVM.

1 голос
/ 26 апреля 2013

В последнее время я работаю над чем-то похожим.Что мне помогло, так это использование библиотеки jni.h, которая появляется при установке java (Java \ jdk [версия] \ include) и создании библиотеки DLL с кодом c / c ++ в Visual Studio.Например:

Test.h

//declare the method you want to implement in c/c++ in the header
//include the jni header
#include <jni.h>
JNIEXPORT void JNICALL Java_Test_print(JNIEnv *, jobject);
//Java_[Class Name]_[Method Name](pointer to JVM, java object);

Test.cpp

extern "C" JNIEXPORT void JNICALL Java_WinampController_printTrackInfo (JNIEnv *env, jobject obj){
    printf("Hey, I'm a java method in c (or not?)\n");
}

Затем создайте dll с Visual Studio и загрузите dll в пределах статический блок.Я не пробовал это без компиляции кода c / c ++ в dll, возможно, есть другой способ вызова кода c / c ++.Но это то, как вы это реализуете.

Test.java

//declare the same method native inside a class in java
public class Test{
    static {
        System.loadLibrary("Test"); //load the dll
    }
    public native void print();
} //after that you just call test.print() normally

Итак, вы просто делаете это и реализуете методы java со всем необходимым c / c ++.

ЕслиВы все еще не знаете, как это сделать, просветите себя здесь:

Спецификация нативного интерфейса Java - Oracle

Нативный интерфейс Java - Википедия

0 голосов
/ 22 сентября 2011

Возможно, вам нужно переосмыслить свой дизайн.Java не является хорошим выбором для такого рода задач.В стандартной библиотеке java нет функции eval(), аналогичной eval() в python или shell.

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

Вы можете, например, использовать некоторые RPC (SOAP, XML-RPC, Corba) между вашим кодом C ++ и отдельным кодом Java.Если вам нужно выполнить какой-нибудь eval() -подобный вызов Java, вы можете использовать Groovy или Jython (оба имеют eval(), доступ ко всей стандартной библиотеке Java и могут запускать обычные классы Java).

0 голосов
/ 22 сентября 2011

Для сценария, который вы описываете JNI, вероятно, лучший путь. Вы бы представляли функциональность вашего приложения на C ++ как DLL, которая может быть включена в Java-приложение и использована в нем.

...