2009-06-14 9 views

Respuesta

34

Sí, puede, pero es un poco intrincado, y funciona de manera reflexiva/no segura (por ejemplo, utiliza la API api que es un poco más limpia que la versión C). En este caso, crea una instancia de Java VM desde dentro del código C. Si su nativa llamada es primero ser llamado desde Java, entonces no hay necesidad de construir una instancia de VM

#include<jni.h> 
#include<stdio.h> 

int main(int argc, char** argv) { 

    JavaVM *vm; 
    JNIEnv *env; 
    JavaVMInitArgs vm_args; 
    vm_args.version = JNI_VERSION_1_2; 
    vm_args.nOptions = 0; 
    vm_args.ignoreUnrecognized = 1; 

    // Construct a VM 
    jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); 

    // Construct a String 
    jstring jstr = env->NewStringUTF("Hello World"); 

    // First get the class that contains the method you need to call 
    jclass clazz = env->FindClass("java/lang/String"); 

    // Get the method that you want to call 
    jmethodID to_lower = env->GetMethodID(clazz, "toLowerCase", 
             "()Ljava/lang/String;"); 
    // Call the method on the object 
    jobject result = env->CallObjectMethod(jstr, to_lower); 

    // Get a C-style string 
    const char* str = env->GetStringUTFChars((jstring) result, NULL); 

    printf("%s\n", str); 

    // Clean up 
    env->ReleaseStringUTFChars(jstr, str); 

    // Shutdown the VM. 
    vm->DestroyJavaVM(); 
} 

Para compilar (en Ubuntu):

g++ -I/usr/lib/jvm/java-6-sun/include \ 
    -I/usr/lib/jvm/java-6-sun/include/linux \ 
    -L/usr/lib/jvm/java-6-sun/jre/lib/i386/server/ -ljvm jnitest.cc 

Nota: que el código de retorno de cada uno de estos métodos deben verificarse para implementar el manejo correcto de errores (he ignorado esto por conveniencia). P.ej.

str = env->GetStringUTFChars(jstr, NULL); 
if (str == NULL) { 
    return; /* out of memory */ 
} 
+1

+1 por ejemplo. ¿Podría también querer incluir enlaces/ejemplos de configurar los encabezados, firmas de funciones, etc.? – poundifdef

+0

su solución es genial, pero ¿cómo cargar o establecer classpath que hemos creado? Por ejemplo HelloWorld.java es decir env_> FindClass ("HelloWorld"); ' –

9

Sí lo es, pero hay que hacerlo a través de JNI: http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html

+0

He visto que JNI solía llamar a C++ desde Java. No sabía que funcionó a la inversa también. – Kieveli

+3

Extraño, siempre he visto que se usa más comúnmente para proporcionar acceso a bibliotecas C++ desde Java, pero funciona en ambos sentidos. –

3

Hay muchas maneras. Here son algunas ideas. Además, los puentes comerciales COM de Java permiten la comunicación COM de C++ a Java (si está utilizando Windows). También debe mirar CNI.

2

Sí, se puede llamar a una función Java desde C++ o C, pero a menos que estés usando algo como COM o CORBA (u otra herramienta de tercera partes que probablemente no soy consciente de) podrás tiene que hacer esto en el contexto de JNI.

Todo el procedimiento para llamar a un método Java de código nativo se describe en el capítulo 4 en el apartado 4.2 denominado "Llamar a Métodos" en la guía de JNI pdf de Sun, que se puede encontrar here.

2

Eche un vistazo a invocation API. Esto le permite cargar e iniciar una JVM desde dentro de su aplicación nativa, y luego invocar métodos desde la aplicación.

En pocas palabras (del documento relacionado)

/* 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); 
1

La siguiente función le permite crear la máquina virtual.

JNIEnv* create_vm(JavaVM ** jvm) 
{ 
    JNIEnv *env; 
    JavaVMInitArgs vm_args; 
    JavaVMOption options[2]; 

    options[0].optionString = "-Djava.class.path=."; 
    options[1].optionString = "-DXcheck:jni:pedantic"; 

    vm_args.version = JNI_VERSION_1_6; 
    vm_args.nOptions = 2; 
    vm_args.options = options; 
    vm_args.ignoreUnrecognized = JNI_TRUE; // remove unrecognized options 

    int ret = JNI_CreateJavaVM(jvm, (void**) &env, &vm_args); 
    if (ret < 0) printf("\n<<<<< Unable to Launch JVM >>>>>\n"); 
    return env; 
} 

Compilar el famoso programa Hello World. La siguiente función intenta llamar al método principal del programa HelloWorld.

int main(int argc, char* argv[]) 
{ 
    JNIEnv* env; 
    JavaVM* jvm; 

    env = create_vm(&jvm); 

    if (env == NULL) return 1; 

    jclass myClass = NULL; 
    jmethodID main = NULL; 


    myClass = env->FindClass("HelloWorld"); 


    if (myClass != NULL) 
     main = env->GetStaticMethodID(myClass, "main", "([Ljava/lang/String;)V"); 
    else 
     printf("Unable to find the requested class\n"); 


    if (main != NULL) 
    { 
     env->CallStaticVoidMethod(myClass, main, " "); 

    }else printf("main method not found") ; 


    jvm->DestroyJavaVM(); 
    return 0; 
} 

función create_vm Ahora ponga y función principal en un solo archivo CPP, incluyen jni.h y compilarlo. Usé MinGW en Windows.

g++ -D_JNI_IMPLEMENTATION_ -I"C:\Program Files\Java\jdk1.6.0_32\include" -I"C:\Program Files\Java\jdk1.6.0_32\include\win32" hello.cpp -L"C:\Program Files\Java\jre6\bin\client" -ljvm -o hello.exe 

Exection Ahora bien, si se ejecuta el exe creado, recibirá un error. jvm.dll not found. Ponga C:\Program Files\Java\jre6\bin\client en su variable de entorno PATH. Ahora puede ejecutar el archivo exe.

Nota: No desplace el archivo jvm.dll.

0

Después de codificar los ejemplos anteriores, debe realizar alguna configuración en su proyecto.

Pasos para enlazar la jvm.lib a su proyecto en Visual Studio:

  • Haga clic derecho sobre el proyecto -> propiedades.
  • En el cuadro de diálogo Propiedades, agregue jvm.lib en el área Enlazador-> Entrada-> Otras dependencias.
  • Por último escribir camino jvm.lib (como "C: \ Archivos de programa \ Java \ jdk1.7.0_60 \ lib") bajo Linker-> General-> AdditionalLibraryDirectories

Después de esos pasos, su proyecto puede enlace a jvm y funciona bien.

Cuestiones relacionadas