2013-06-05 13 views
5

Sto cercando di acquisire familiarità con l'API JNI ma non riesco a ottenere un programma C++ di esempio da compilare. Ho ottenuto lo stesso esempio di compilazione ed esecuzione in linux (dopo aver postato la domanda nel link sottostante) ma non riesco a ottenerlo compilato in Windows; Sto usando mingw g ++. Ho cambiato tutti i percorsi di inclusione in percorsi Windows e jni.h si trova in fase di compilazione ma non in jvm.dll.riferimento non definito alle finestre `JNI_CreateJavaVM '

undefined reference to `JNI_CreateJavaVM' linux

Ecco i comandi che ho provato usando per compilare:

g++ -g -I"C:\Program Files (x86)\Java\jdk1.7.0_21\include" -I"C:\Program Files (x86)\Java\jdk1.7.0_21\include\win32" -L"C:\Program Files (x86)\Java\jdk1.7.0_21\jre\bin\server" callJava.cpp -ljvm 

e ...

**same as above with the additional** : -L"C:\Program Files (x86)\Java\jdk1.7.0_21\lib" 

L'errore che ottengo è:

undefined reference to `[email protected]' 

e il cpp in fase di compilazione:

#include <jni.h> 

int main(){ 

    //firstTest(); 
    JavaVM *jvm; 
    JNIEnv *env; 

    JavaVMInitArgs vm_args; 
    JavaVMOption options[1]; 
    options[0].optionString = "-Djava.class.path=C:/Users/Ron/Dropbox/jni/simple/ctojava/win"; 
    vm_args.version = JNI_VERSION_1_6; 
    vm_args.options = options; 
    vm_args.nOptions = 1; 
    vm_args.ignoreUnrecognized = JNI_FALSE; 

    int res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args); 

    jclass cls = env->FindClass("Hello"); 
    jmethodID mid = env->GetStaticMethodID(cls, "staticInt", "(I)I"); 
    env->CallStaticVoidMethod(cls, mid,10); 

    jvm->DestroyJavaVM(); 
} 

Ho esaminato molti esempi ma non riesco ancora a trovare una soluzione. Qualsiasi aiuto è apprezzato!

UPDATE: Sono abbastanza sicuro che la l'jvm.dll è situato perché se mi tolgo la -L "path_to_jvm" allora ottengo l'errore:

mingw32/bin/ld.exe: cannot find -ljvm 

Come ho detto, questo approccio esatto funziona in Linux, che altro mi manca per Windows?

+0

Può essere un problema collegare alle librerie create con MSVC da g ++. Vedi questo post di interoperabilità: http://www.mingw.org/wiki/MixingCompilers. Hai considerato di utilizzare Visual Studio invece? – maba

+0

@ maba- Ho provato anche in Visual Studio, ma ottengo lo stesso risultato. Sai per certo che il file jvm.dll è stato creato con MSVC? Immagino che non lo sia, ma è solo una supposizione. – RBI

+1

@RBI È costruito con MSVC. Il modo in cui i nomi delle funzioni sono stravolti nella tabella di esportazione è un regalo. – greatwolf

risposta

3

Il problema che hai incontrato può essere riassunto brevemente come un problema di decorazione del nome. Il linker non è riuscito a trovare la funzione con il nome dato perché è decorato in modo diverso nello jvm.dll.

Guardando l'errore iniziale che hai:

undefined reference to '[email protected]' 

E 'accennando a due cose:

  1. Il @12 suffisso alla fine indica che JNI_CreateJavaVM utilizza supposely la convenzione stdcall.
  2. Il prefisso _imp_ indica che questa funzione proviene da una libreria di importazione che reindirizza a una dll caricata esternamente che ha questa funzione visibile nella sua tabella di esportazione.

Il prototipo di funzione in jni.h:

_JNI_IMPORT_OR_EXPORT_ 
jint JNICALL JNI_CreateJavaVM(JavaVM **, void **, void *); 

probabilmente si presenta così dopo la pre-elaborazione:

__declspec(dllimport) jint __stdcall 
JNI_CreateJavaVM(JavaVM **, void **, void *); 

Ora il linker GNU che viene fornito con MinGW in grado di lavorare con i simboli da .a, COFF di msvc formato .lib e .dll direttamente. Nel comando originale, ha trovato solo jvm.dll nel percorso di ricerca fornito (-L ...), quindi ha provato a utilizzarlo.

Il problema è che nella tabella esportazione jvm.dll s' la funzione JNI_CreateJavaVM è un-decorato in modo che appaia come una funzione cdecl. Questo nome non corrisponde a ciò che si aspetta il linker in modo da ottenere l'errore di riferimento non definito.

Dall'esame del kit Java Dev, include una libreria di importazione a jdk1.7.0_21\lib\jvm.lib che ha la decorazione del nome corretta per questo simbolo. Il comando revisionato funziona perché aggiungendo -L jdk1.7.0_21\lib al percorso di ricerca che ora collega a jvm.lib e non a jvm.dll.

+2

Molto ben spiegato, grazie per aver chiarito questo per me. – RBI

+0

Ciao. Sto collegando al file jvm.lib e mi dà ancora questo errore. Qualche idea? Il comando utilizzato è g ++ "-LC: \\ Programmi \\ Java \\ jdk1.8.0_112 \\ lib" -o voce_synth.exe synthesisTest.o -ljvm – Renato

+0

@Renato lo switch '-ljvm' aggiunge un' lib * 'prefisso al file di importazione. IOW con '-ljvm' g ++ cerca' libjvm.a'. Prova '-l: jvm.lib' o semplicemente passando il nome del file con il path completo così com'è senza' -l'. – greatwolf

2

Trovato! dopo aver letto il post qui sotto sono stato in grado di compilare ed eseguire l'esempio con il link aggiuntivo nel comando di compilazione, al fine di collegare il jvm.lib:

-L"C:\Program Files (x86)\Java\jdk1.7.0_21\lib" 

Link: Linking JNI to visual studio 2008

Io non sono un c/C++ esperto quindi se qualcuno vuole spiegare perché questo link aggiuntivo è richiesto quando non è in linux, sarei felice di accettare la tua risposta.

Problemi correlati