Intégrer Java dans une application C++?


J'ai une application écrite en C++ et je suis capable d'étendre la fonctionnalité des applications en écrivant des plugins en C++ pour cela.

Ce que je veux essentiellement faire, c'est intégrer Java dans cette application. Cela a déjà été fait avec Python (pas fait par moi).

J'ai lu quelque chose sur JNI mais il y a toujours le discours d'un programme complet qui utilise des classes Java.

Ce que j'aimerais faire, c'est utiliser des classes de C++ en Java pour interagir avec le application.
C'est une application 3D dans ce cas, appelée Cinema 4D.

Existe-t-il un moyen de compiler et d'évaluer le code Java pendant que l'application est en cours d'exécution (dans une sorte de langage de script) en utilisant JNI ou quelque chose comme ça ?

Exemple de code imaginaire après l'intégration:

import c4d.documents.*;

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

Ce code doit interagir avec Cinema 4D pour supprimer l'objet sélectionné.

Author: Andy Thomas, 2011-09-21

6 answers

Vous pouvez intégrer une JVM dans votre application. Le livre de référence officiel d'Oracle contient plus de détails. Le synopsis est:

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

Vous pouvez faire des choses beaucoup plus sophistiquées si vous le souhaitez (par exemple, des chargeurs de classe personnalisés) mais c'est à peu près tout en termes de strict minimum nécessaire pour qu'une JVM fonctionne dans votre application.

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

Il semble y avoir une certaine confusion quant à savoir si vous voulez intégrer Java dans l'application C++ ou l'inverse. Je vais prendre chaque cas.

  1. Pour intégrer java dans l'application c++, vous pouvez faire un appel de socket au programme java. À la fin java, vous utilisez SocketServer et à la fin C++, vous utilisez la bibliothèque General Socket Layer. C'est de loin l'approche la plus simple et la plus évolutive. À mesure que votre charge de travail java augmente, vous continuez à ajouter de la jvm supplémentaire. Un peu compliqué à déployer mais, il fonctionne vraiment bien.

  2. Pour intégrer l'application C++ en java. C'est simple. Vous compilez l'application C++ dans une bibliothèque partagée et utilisez JNI pour l'invoquer.

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

Ce que je veux essentiellement faire, c'est intégrer Java dans cette application. Cela a déjà été fait avec Python (pas fait par moi).

L'API d'invocation JNI prend en charge cela, comme décrit par @awoodland. Voici un lien actuel, pour Java 6/7.

Ce que j'aimerais faire, c'est utiliser des classes de C++ en Java pour interagir avec l'application. C'est une application 3D dans ce cas, appelée Cinema 4D.

Pour cela, vous pouvez utiliser l'un des suivant:

  • Méthodes natives Java implémentées en C
  • JNA
  • SWIG

Existe-t-il un moyen de compiler et d'évaluer le code Java pendant que l'application est en cours d'exécution (dans une sorte de langage de script) en utilisant JNI ou quoi que ce soit comme elle ?

BeanShell ou Groovy, parmi d'autres, pourraient être d'intérêt pour vous. Les deux prennent en charge le code interprété dynamiquement qui s'exécute sur la JVM.

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

J'ai travaillé dans quelque chose de similaire ces derniers temps. Ce qui a fonctionné pour moi était d'utiliser la bibliothèque jni.h cela vient lorsque vous installez java(Java \ jdk[version] \ include) et créez une dll avec du code c/c++ dans visual studio. Par exemple:

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

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

Ensuite, créez une dll avec Visual Studio et chargez la dll dans un statique bloquer. Je n'ai pas essayé cela sans compiler le code c/c++ dans une dll, peut-être qu'il existe une autre façon d'appeler le c / c++ code. Mais c'est comme ça que vous l'implémentez.

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

Donc, vous faites simplement cela et implémentez des méthodes java avec tout le c/c++ que vous voulez.

Si vous ne savez toujours pas comment le faire, éclairez-vous ici:

Il s'agit d'un logiciel de gestion de données.]}

L'interface Java native-Wikipedia

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

Pour le scénario que vous décrivez JNI est probablement la meilleure façon d'aller. Vous exposeriez les fonctionnalités de votre application C++ en tant que DLL pouvant être incorporée et utilisée à partir d'une application Java.

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

Vous devez probablement repenser votre conception. Java n'est pas un bon choix pour ce genre de tâches. Il n'y a pas de fonction eval() dans la bibliothèque standard java similaire à eval() de python ou de shell.

Vous pouvez créer une machine virtuelle java en code C++ en utilisant JNI mais c'est un peu lourd. Il existe toujours un problème pour créer un bytecode à partir d'une source java. Vous devrez intégrer beaucoup de code pour compiler et exécuter du code java en C++. Ne pas le faire. Il doit y avoir une meilleure solution.

Vous pouvez par exemple utiliser RPC (SOAP, XML-RPC, Corba) entre votre code C++ et votre code java séparé. Si vous avez besoin de faire une invocation java de type eval(), vous pouvez utiliser Groovy ou Jython (les deux ont eval(), accès à toutes les bibliothèques java standard et peuvent exécuter des classes java régulières).

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