Встраивать Java в приложение C++?
Я получил приложение, написанное на 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 ответов
Вы можете встроить 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 в вашем приложении.
Кажется, есть некоторая путаница по поводу того, хотите ли вы встроить Java в приложение C++ или наоборот. Я возьму каждый случай.
Для встраивания Java в приложение C++, вы можете сделать вызов сокета для Java-программы. На стороне Java вы используете SocketServer, а на стороне C++ - библиотеку General Socket Layer. Это, безусловно, самый простой и масштабируемый подход. Поскольку ваша рабочая нагрузка на Java продолжает расти, вы продолжаете добавлять дополнительные jvm. Немного сложен в развертывании, но работает очень хорошо.
Для встраивания приложения C++ в Java. Это просто Вы компилируете приложение C++ в общую библиотеку и используете JNI для его вызова.
Что я в основном хочу сделать, так это встроить Java в это приложение. Это уже было сделано с Python (не сделано мной).
API вызова JNI поддерживает это, как описано @awoodland. Вот текущая ссылка для Java 6/7.
Я хотел бы использовать классы из C++ в Java для взаимодействия с приложением. В данном случае это 3D-приложение, которое называется Cinema 4D.
Для этого вы можете использовать одно из следующих:
Есть ли способ компилировать и оценивать код Java во время работы приложения (на каком-либо языке сценариев) с использованием JNI или чего-то подобного?
BeanShell или Groovy, помимо прочего, могут вас заинтересовать. Оба поддерживают динамически интерпретируемый код, который выполняется на JVM.
Я работал над чем-то похожим в последнее время. Что мне помогло, так это использование библиотеки 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++.
Если вы все еще не знаете, как это сделать, просветите себя здесь:
Для сценария, который вы описываете, JNI, вероятно, лучший путь. Вы бы представляли функциональность вашего приложения на C++ как DLL, которая может быть включена в Java-приложение и использована в нем.
Вам, вероятно, нужно переосмыслить свой дизайн. Java не является хорошим выбором для такого рода задач. Здесь нет eval()
функция в стандартной библиотеке Java похожа на eval()
из питона или оболочки.
Вы можете создать java VM в коде C++, используя JNI, но это довольно тяжело. Есть еще проблема, как создать байт-код из Java-источника. Вам придется встраивать много кода для компиляции и запуска кода Java в C++. Не делай этого. Там должно быть лучшее решение.
Например, вы можете использовать некоторые RPC (SOAP, XML-RPC, Corba) между вашим кодом C++ и отдельным кодом Java. Если вам нужно сделать некоторые eval()
Подобно Java-вызову, вы можете использовать Groovy или Jython (оба имеют eval()
Доступ ко всей стандартной библиотеке Java и может запускать обычные классы Java).