Incorporare Java in un'applicazione C++?


Ho un'applicazione scritta in C++ e sono in grado di estendere le funzionalità delle applicazioni scrivendo plugin in C++ per questo.

Quello che fondamentalmente voglio fare è incorporare Java in questa applicazione. Questo è già stato fatto con Python (non fatto da me).

Ho letto qualcosa su JNI ma c'è sempre il discorso da un programma completo che utilizza classi Java.

Quello che mi piacerebbe fare è usare le classi da C++ in Java per interagire con applicazione.
È un'app 3D in questo caso, chiamata Cinema 4D.

C'è un modo per compilare e valutare il codice Java mentre l'applicazione è in esecuzione (in una sorta di linguaggio di scripting) usando JNI o qualcosa di simile ?

Esempio di codice immaginario dopo l'incorporamento:

import c4d.documents.*;

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

Questo codice dovrebbe interagire con Cinema 4D per eliminare l'oggetto selezionato.

Author: Andy Thomas, 2011-09-21

6 answers

È possibile incorporare una JVM all'interno dell'applicazione. Oracle libro di riferimento ufficiale ha alcuni dettagli in più. La sinossi di esso è:

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

Puoi fare cose molto più sofisticate se vuoi (ad esempio caricatori di classi personalizzati) ma questo è tutto in termini di minimo necessario per far funzionare una JVM all'interno della tua applicazione.

 49
Author: Flexo, 2015-05-26 08:40:04

Sembra esserci una certa confusione se si desidera incorporare Java nell'app C++ o viceversa. Prendero ' ogni caso.

  1. Per incorporare java nell'app c++, è possibile effettuare una chiamata socket al programma java. Alla fine di java, si utilizza SocketServer e alla fine di C++, si utilizza la libreria generale Socket Layer. Questo è di gran lunga l'approccio più semplice e scalabile. Poiché il carico di lavoro java continua ad aumentare, si continua ad aggiungere jvm aggiuntive. Leggermente complicato da distribuire ma funziona davvero bene.

  2. Per incorporare l'app C++ in java. Questo è semplice. Si compila l'app C++ in una libreria condivisa e si utilizza JNI per invocarla.

 4
Author: RHT, 2011-09-21 21:41:33

Quello che fondamentalmente voglio fare è incorporare Java in questa applicazione. Questo è già stato fatto con Python (non fatto da me).

L'API di invocazione JNI supporta questo, come descritto da @awoodland. Ecco un collegamento corrente, per Java 6/7.

Quello che mi piacerebbe fare è usare le classi da C++ in Java per interagire con l'applicazione. È un'app 3D in questo caso, chiamata Cinema 4D.

Per questo è possibile utilizzare uno dei di seguito:

C'è un modo per compilare e valutare il codice Java mentre l'applicazione è in esecuzione (in una sorta di linguaggio di scripting) usando JNI o altro ti piace ?

BeanShell o Groovy , tra gli altri, potrebbero interessarti. Entrambi supportano il codice interpretato dinamicamente che viene eseguito sulla JVM.

 2
Author: Andy Thomas, 2011-09-21 21:19:41

Ultimamente ho lavorato in qualcosa di simile. Quello che ha funzionato per me è stato usare la biblioteca jni.h che viene quando si installa java (Java \ jdk [versione] \ include) e si crea una dll con codice c/c++ in visual studio. Ad esempio:

Prova.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);

Prova.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");
}

Quindi creare una dll con Visual Studio e caricare la dll all'interno di un statico blocco. Non l'ho provato senza compilare il codice c / c++ in una dll, forse c'è un altro modo per chiamare il c / c++ codice. Ma è così che lo implementi.

Prova.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

Quindi, lo fai e implementi i metodi java con tutto il c/c++ che desideri.

Se ancora non sai come farlo, illuminati qui:

Specifica dell'interfaccia nativa Java-Oracle

Interfaccia nativa Java-Wikipedia

 1
Author: 0rkan, 2015-08-09 22:59:59

Per lo scenario che stai descrivendo JNI è probabilmente il modo migliore per andare. Potresti esporre la funzionalità della tua app C++ come DLL che può essere incorporata e utilizzata da un'applicazione Java.

 0
Author: Perception, 2011-09-21 20:45:48

Probabilmente hai bisogno di ripensare il tuo design. Java non è una buona scelta per questo tipo di attività. Non esiste una funzione eval() nella libreria standard java simile a eval() da python o shell.

Puoi creare una VM java in codice C++ usando JNI ma è piuttosto pesante. C'è ancora un problema su come creare un bytecode da una fonte java. Dovrai incorporare molto codice per compilare ed eseguire codice java in C++. Non farlo. Ci deve essere una soluzione migliore.

Puoi ad esempio usare alcuni RPC (SOAP, XML-RPC, Corba) tra il codice C++ e il codice java separato. Se hai bisogno di fare un po ' di eval()-come l'invocazione java, puoi usare Groovy o Jython (entrambi hanno eval(), accesso a tutte le librerie java standard e possono eseguire classi java regolari).

 -2
Author: Michał Šrajer, 2011-09-21 21:02:52