2013-06-05 46 views
5

我想熟悉JNI API,但无法获得一个示例C++程序来编译。我得到了相同的样本来编译和运行在Linux中(在下面的链接发布问题后),但不能得到它在Windows编译;我正在使用mingw g ++。我已将所有包含路径更改为windows路径,并且jni.h位于编译时,但不是jvm.dll。未定义的引用'JNI_CreateJavaVM'窗口

undefined reference to `JNI_CreateJavaVM' linux

这里是我试过的命令使用编译:

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 

和...

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

我得到的错误是:

undefined reference to `[email protected]' 

和正在编译的cpp:

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

我看了很多例子,但仍找不到解决方案。任何帮助表示赞赏!

更新:我敢肯定的是的jvm.dll位于因为如果我删除了-L“path_to_jvm”然后我得到的错误:

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

就像我说的,这个确切的方法在Linux中工作,还有什么我缺少的Windows?

+0

链接到使用g ++创建的MSVC库可能会有问题。看到这个互操作性的帖子:http://www.mingw.org/wiki/MixingCompilers。你有没有考虑过使用Visual Studio呢? – maba

+0

@ maba-我已经尝试在视觉工作室,但我得到了同样的结果。你知道jvm.dll是用MSVC构建的吗?我猜这不是,但这只是一个猜测。 – RBI

+1

@RBI它是用MSVC构建的。函数名称在输出表中被破坏的方式是免费的。 – greatwolf

回答

3

您遇到的问题可以简要归结为名称装饰问题。链接器找不到具有给定名称的函数,因为它在jvm.dll中的装饰方式不同。

看着你得到了最初的错误:

undefined reference to '[email protected]' 

它暗示了两件事情:

  1. @12后缀在最后指出JNI_CreateJavaVM supposely使用STDCALL约定。
  2. _imp_前缀表示该函数来自导入库,该导入库将重定向到外部加载的dll,该dll在其导出表中可以看到此函数。

的函数原型在jni.h

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

可能看起来像这样预处理后:

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

现在自带的MinGW可以用符号从.a,MSVC的COFF工作GNU链接直接格式.lib.dll。在您的原始命令中,它仅在所提供的搜索路径(-L ...)中找到了jvm.dll,因此它试图使用它。

的问题是,在jvm.dll导出表JNI_CreateJavaVM功能未装饰的,所以它看起来像一个CDECL功能。该名称与链接器期望的名称不匹配,因此您会收到未定义的引用错误。

从查看Java开发工具包,它包含一个导入库jdk1.7.0_21\lib\jvm.lib,它具有此符号的正确名称装饰。您的修改后的命令有效,因为通过将-L jdk1.7.0_21\lib添加到搜索路径,它现在链接到jvm.lib而不是jvm.dll

+2

非常好的解释,谢谢澄清这对我。 – RBI

+0

你好。我链接到jvm.lib文件,它仍然给我这个错误。任何想法?使用的命令是g ++“-LC:\\ Program Files \\ Java \\ jdk1.8.0_112 \\ lib”-o voce_synth.exe synthesisTest.o -ljvm – Renato

+0

@Renato'-ljvm'开关附加一个'lib * '输入文件的前缀。 IOW用'-ljvm'查找'libjvm.a'。尝试使用'-l:jvm.lib'或只传递完全路径的文件名,因为没有'-l'。 – greatwolf

2

Got it!阅读下面后,我能够编译和运行,以便在编译命令附加链接样品到jvm.lib链接后:

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

链接:Linking JNI to visual studio 2008

我没有C/c + +专家,所以如果任何人想解释为什么这个额外的链接是不需要的时候,我会很高兴接受你的答案。