2011-09-21 9 views
17

Obtuve una aplicación escrita en C++ y puedo ampliar la funcionalidad de las aplicaciones escribiendo complementos en C++ para ello.¿Incrustar Java en una aplicación C++?

Lo que básicamente quiero hacer es incorporar Java en esta aplicación. Esto ya se ha hecho con Python (no hecho por mí).

He leído algo sobre JNI, pero siempre existe el discurso de un programa completo que utiliza clases de Java.

Lo que me gustaría hacer es utilizar clases de C++ en Java para interactuar con la aplicación.
Es una aplicación 3D en este caso, llamada Cinema 4D.

¿Hay alguna forma de compilar y evaluar código Java mientras la aplicación se está ejecutando (en algún tipo de lenguaje de scripting) usando JNI o ​​algo similar?

Ejemplo código imaginario después se realizó la incrustación:

import c4d.documents.*; 

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

Este código debe interactuar con el cine 4D para borrar el objeto seleccionado.

+0

¿Necesita completa Java SE o sólo algunos mínimos VM? –

+0

¿Por qué dices "algún tipo de lenguaje de scripting", si ya has determinado que este idioma debe ser Java? – jalf

+0

@ MichałŠrajer Esto en realidad sigue abierto, la interacción básica entre Java y la aplicación sería genial para el comienzo. –

Respuesta

37

Puede incrustar una JVM dentro de su aplicación. Oracle official reference book tiene más detalles. La sinopsis de la misma es:

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

Se pueden hacer cosas mucho más sofisticados si quieres (por ejemplo cargadores de clases personalizados), pero eso es todo en cuanto a lo mínimo necesario para obtener una JVM de trabajo dentro su aplicación.

+0

Ahora, ¿no es esto para llamar a un método Java de C++? De hecho, lo necesitaría al revés :) –

+2

Con swig puedes generar enlaces que te permitan hacer llamadas a C++ desde Java. La pregunta implicaba que lo querías de esta manera. También puedes hacer ambas cosas en un solo programa. – Flexo

+0

Mis dos centavos: dado que OP quiere cargar complementos, creo que también debería leer acerca de cómo los cargadores de clases personalizadas le permiten leer un "contenedor de complementos". Además, necesita clases Java con métodos nativos (es decir, JNI) para llamar a C++ desde Java. –

0

Para el escenario que está describiendo JNI es probablemente la mejor manera de hacerlo. Expondrías la funcionalidad de tu aplicación C++ como una DLL que se puede incorporar y usar desde una aplicación Java.

-1

Probablemente necesite replantear su diseño. Java no es una buena opción para este tipo de tareas. No hay función eval() en la biblioteca estándar de Java similar a eval() de python o shell.

Puede crear una VM Java en código C++ utilizando JNI, pero es algo pesado. Todavía existe el problema de cómo crear un bytecode a partir de una fuente Java. Deberá incrustar una gran cantidad de código para compilar y ejecutar código java en C++. No hagas eso. Debe haber una mejor solución.

Puede, por ejemplo, utilizar algunos RPC (SOAP, XML-RPC, Corba) entre su código C++ y el código java por separado. Si necesita hacer alguna invocación de Java tipo eval(), puede usar Groovy o Jython (ambos tienen eval(), acceso a toda la biblioteca java estándar y pueden ejecutar clases regulares de Java).

2

Lo que básicamente quiero hacer es incorporar Java en esta aplicación. Esto ya se ha hecho con Python (no hecho por mí).

La API de invocación JNI es compatible con esto, tal como lo describe @awoodland. Here's a current link, for Java 6/7.

Lo que me gustaría hacer es utilizar clases de C++ en Java para interactuar con la aplicación. Es una aplicación 3D en este caso, llamada Cinema 4D.

Para este propósito puede utilizar uno de los siguientes:

  • métodos nativos Java implementados en C
  • JNA
  • SWIG

¿Hay una manera de compilar y evaluar el código Java mientras la aplicación se está ejecutando (en algún tipo de lenguaje de script) utilizando JNI o ​​cualquier cosa me gusta?

BeanShell o Groovy, entre otros, podría ser de interés para usted. Ambos admiten el código interpretado de forma dinámica que se ejecuta en la JVM.

+0

Para llamar a C++ desde Java, recomendaría también echarle un vistazo a [BridJ] (http://code.google.com/p/bridj) + [JNAerator] (http://code.google.com/p/jnaerator). – zOlive

3

Parece haber cierta confusión sobre si desea incrustar Java en la aplicación C++ o al revés. Tomaré cada caso.

  1. Para incrustar java en la aplicación C++, puede hacer una llamada de socket al programa java. En java end, usa SocketServer y en el extremo de C++, usa la biblioteca General Socket Layer. Este es de lejos el enfoque más fácil y escalable. A medida que su carga de trabajo java sigue aumentando, usted sigue agregando jvm adicional. Ligeramente complicado de implementar, pero funciona muy bien.

  2. Para incrustar la aplicación C++ en java. Esto es simple. Compila la aplicación C++ en una biblioteca compartida y usa JNI para invocarla.

1

He estado trabajando en algo similar últimamente. Lo que funcionó para mí fue usar la biblioteca jni.h que viene cuando instalas java (Java \ jdk [versión] \ include) y creas un dll con código c/C++ en visual studio. Por ejemplo:

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

A continuación, crear un archivo DLL con Visual Studio y cargar el archivo DLL dentro de un bloque estático. No intenté sin compilar el código c/C++ en un dll, quizás haya otra manera de llamar al código c/C++. Pero así es como lo implementas.

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 

lo tanto, usted acaba de hacer eso y poner en práctica los métodos de Java con toda c/C++ desea.

Si todavía no sabe cómo hacerlo, iluminar a ti mismo aquí:

Java Native Interface Specification - Oracle

Java Native Interface - Wikipedia

Cuestiones relacionadas