为什么在Windows上调用MinGW编译的函数(未加载库)时出现UnsatisfiedLinkError? [英] Why do I get UnsatisfiedLinkError when calling a MinGW-compiled function (not loading the library) on Windows?

查看:66
本文介绍了为什么在Windows上调用MinGW编译的函数(未加载库)时出现UnsatisfiedLinkError?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Windows上的Eclipse制作一个简单的JNI测试应用程序.我的C ++编译器是MinGW 4.6.2.当我尝试在测试DLL中调用函数时,Java抛出UnsatisfiedLinkError(DLL本身加载没有问题).我已验证我的DLL导出了一个与javah实用程序生成的函数同名的"C"函数.

I'm making a simple JNI test app using Eclipse on Windows. My C++ compiler is MinGW 4.6.2. Java is throwing an UnsatisfiedLinkError when I try to invoke a function in my test DLL (the DLL itself loads without problem). I have verified that my DLL exports a "C" function with the same name as the function generated by the javah utility.

如何尝试调用该函数可能会产生链接错误?(此外,是否有任何方法可以更详细地了解未找到什么符号秃顶的说法是UnsatisfiedLinkError几乎是无用的.)

How could trying to invoke the function possibly generate a link error? (Also, is there any way to get more detail as to what symbol isn't being found? A bald statement that there's an UnsatisfiedLinkError is next to useless.)

package com.xyz.jsdi_test;

import java.io.File;

public class JSDI
{
    public static native void func(
        String str,
        int i,
        Integer ii,
        long j /* 64 bits */,
        Long jj,
        byte[] b
    );
    public static void dummy()
    {
        System.out.println("JSDI.dummy()");
    }
    static
    {
        File f = new File("..\\jsdi\\bin\\jsdi.dll");
        System.out.println("Preparing to load: " + f);
        System.load(f.getAbsolutePath());
        System.out.println("Successfully loaded: " + f);
    }

这是javah的相应输出:

Here is the corresponding output from javah:

...
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_xyz_jsdi_test_JSDI
 * Method:    func
 * Signature: (Ljava/lang/String;ILjava/lang/Integer;JLjava/lang/Long;[B)V
 */
JNIEXPORT void JNICALL Java_com_xyz_jsdi_1test_JSDI_func
  (JNIEnv *, jclass, jstring, jint, jobject, jlong, jobject, jbyteArray);

#ifdef __cplusplus
}
#endif

...以及我如何实现该功能...:

extern "C"
{

JNIEXPORT void JNICALL Java_com_xyz_jsdi_1test_JSDI_func(
    JNIEnv * env,
    jclass _class,
    jstring str,
    jint i,
    jobject ii,
    jlong j,
    jobject jj,
    jbyteArray b
)
{
    // don't do anything...let's just try to get called successfully...
}

} // extern "C"

这是我尝试调用它的方式.

...

public static void main(String[] args)
{
    JSDI.dummy(); // cause class to load, which should cause System.load() to run.
    JSDI.func("hello", 0, 0, 0L, 0L, (byte[])null);
}

最后,这是输出:

Preparing to load: ..\jsdi\bin\jsdi.dll
Successfully loaded: ..\jsdi\bin\jsdi.dll
JSDI.dummy()
java.lang.UnsatisfiedLinkError: com.xyz.jsdi_test.JSDI.func(Ljava/lang/String;ILjava/lang/Integer;JLjava/lang/Long;[B)V
   at com.xyz.jsdi_test.JSDI.func(Native Method)
   at com.xyz.jsdi_test.SimpleTest.main(SimpleTest.java:24)

推荐答案

解决了它-哇!

事实证明,MSVC在__stdcall函数的名称前加了下划线. MinGW没有. Windows JVM显然需要'_'前缀.我在函数名前加上'_'并用MinGW重建后,一切正常进行.

It turns out that MSVC prepends an underscore to the name of __stdcall functions. MinGW does not. The Windows JVM apparently expects the '_' prefix. As soon as I prepended '_' to the function name and rebuilt with MinGW, everything worked just dandy.

例如:

JNIEXPORT void JNICALL Java_com_xyz_jsdi_1test_JSDI_func ==> _Java_com_xyz_jsdi_1test_JSDI_func

编辑: MinGW随附的dlltool实用程序的--add-stdcall-underscore功能可以为您透明地解决此问题.在您的Makefile中进行设置,您无需担心为不同的编译器使用不同版本的实际源代码.请参阅此链接.

EDIT: The --add-stdcall-underscore feature of the dlltool utility included with MinGW can solve this problem for you transparently. Set it up in your Makefile and you don't need to worry about having different versions of the actual source code for different compilers. See at this link.

这篇关于为什么在Windows上调用MinGW编译的函数(未加载库)时出现UnsatisfiedLinkError?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆