Встраивать Java в приложение на С++?
У меня есть приложение, написанное на С++, и я могу расширить функциональность приложений, написав для него плагины на С++.
В основном я хочу включить Java в это приложение. Это уже было сделано с Python (не сделано мной).
Я прочитал кое-что о JNI, но всегда есть речь из полной программы, которая использует классы Java.
Что я хотел бы сделать, так это использовать классы из С++ в 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 для удаления выбранного объекта.
Ответы
Ответ 1
Вы можете встраивать 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 в вашем приложении.
Ответ 2
Кажется, есть некоторая путаница в том, хотите ли вы встроить Java в приложение С++ или наоборот. Я возьму каждый случай.
-
Для встраивания java в приложение С++ вы можете сделать вызов сокета в java-программу. В конце java вы используете SocketServer и на конце С++ используется библиотека General Socket Layer. Это, безусловно, самый простой и масштабируемый подход. Поскольку ваша рабочая нагрузка java продолжает расти, вы продолжаете добавлять дополнительные jvm. Немного сложный для развертывания, но он работает очень хорошо.
-
Вложение приложения С++ в java. Это просто. Вы компилируете приложение С++ в общую библиотеку и используете JNI для его вызова.
Ответ 3
В основном я хочу включить Java в это приложение. Это уже было сделано с Python (не сделано мной).
API поддержки JNI поддерживает это, как описано в @awoodland. Здесь текущая ссылка для Java 6/7.
Что я хотел бы сделать, так это использовать классы из С++ в Java для взаимодействия с приложением. Это 3D-приложение в этом случае называется Cinema 4D.
Для этого вы можете использовать одно из следующих действий:
- Собственные методы Java, реализованные в C
- JNA
- SWIG
Есть ли способ скомпилировать и оценить код Java, пока приложение (на каком-то языке сценариев) с использованием JNI или чего-то еще нравится?
BeanShell или Groovy, среди другие, могут вас заинтересовать. Оба поддерживают динамически интерпретируемый код, который работает на JVM.
Ответ 4
В последнее время я работал над чем-то подобным. Для меня работала библиотека jni.h, которая появляется, когда вы устанавливаете java (Java\jdk [version]\include) и создаете dll с кодом 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 в блок static.
Я не пробовал это, не компилируя код c/С++ в dll, возможно, есть еще один способ вызвать код 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/С++, которые вы хотите.
Если вы все еще не знаете, как это сделать, просветите себя здесь:
Спецификация интерфейса Java Native - Oracle
Java Native Interface - Википедия
Ответ 5
Для сценария, который вы описываете JNI, вероятно, лучший способ. Вы бы разоблачили функциональность своего С++-приложения как DLL, которая может быть включена в Java-приложение и использоваться с него.
Ответ 6
Вам, вероятно, нужно переосмыслить свой дизайн. Java не является хорошим выбором для таких задач. Нет функции eval()
в стандартной библиотеке java, подобной eval()
, из python или оболочки.
Вы можете создать Java-виртуальную машину в С++-коде, используя JNI, но это тяжело. По-прежнему существует проблема с созданием байт-кода из источника java. Вам нужно будет встроить много кода для компиляции и запуска Java-кода в С++. Не делай этого. Должно быть лучшее решение.
Вы можете, например, использовать RPC (SOAP, XML-RPC, Corba) между кодом С++ и отдельным кодом Java. Если вам нужно выполнить какой-то eval()
-подобный java-вызов, вы можете использовать Groovy или Jython (оба имеют eval()
, доступ ко всей стандартной java-библиотеке и могут запускать обычные классы Java).