• Java中调用c/c++语言出现Exception in thread "main" java.lang.UnsatisfiedLinkError: Test.testPrint(Ljava/lang/String;)V...错误


    错误:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: Test.testPrint(Ljava/lang/String;)V
    at Test.testPrint(Native Method)
    at Test.main(Test.java:8)

    解决方法:

    昨天一天都在想办法解决这个问题,操作步骤按照教程来的,怎么会出错呢?
    想了半天,觉得还是dll文件生成的不对。所以,最后决定把codeblocks换成visual c++来编译生成dll文件,最后一试成功了。

    ------------------------------我是分割线----------------------------------------------------------------------------------------------------------------

    Java中如何调用c/c++

    1、首先打开eclipse,新建一个eclipse工程,编写一个java类。

    如下所示:

    public class Test {
    public native void testPrint(String str);//1


    public static void main(String[] args){
    System.loadLibrary("TestAgain");//2


    Test test = new Test();
    test.testPrint("this is a test");
    }

    }

    分析这个程序,1处使用native关键字申明了一个本地方法,这个方法我们在后面要用c/c++实现

    2处则是在java中通过libname:TestAgain加载本地方法库。

    这里可以使用System.loadLibrary("xxx");//xxx是生成的dll文件的名字加载本地方法库,也可以通过System.load("E:/eclipseWork/Test/TestAgain.dll")来加载本地方法库,load方法里面需要填写绝对路径。

    2、然后使用 javac -d . Test.java 生成类文件

    3、再使用 javah -jni Test 生成.h文件 

    生成的.h文件如下

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Test */

    #ifndef _Included_Test
    #define _Included_Test
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: Test
    * Method: testPrint
    * Signature: (Ljava/lang/String;)V//1
    */
    JNIEXPORT void JNICALL Java_Test_testPrint
    (JNIEnv *, jobject, jstring); //2

    #ifdef __cplusplus
    }
    #endif
    #endif

    这个和我们平常的.h文件没有什么差别,都是用来申明函数的,不过它是机器自动生成的,所以不要修改。

    1处,是一个标记符,当从本地方法端访问java端的时候就会用到。

    java类型 Signature 备注
    boolean Z  
    byte B  
    char C  
    short S  
    int I  
    long L  
    float F  
    double D  
    void V  
    object L用/分割的完整类名 例如: Ljava/lang/String表示String类型
    Array [签名 例如: [I表示int数组, [Ljava/lang/String表示String数组
    Method (参数签名)返回类型签名 例如: ([I)I表示参数类型为int数组, 返回int类型的方法

    (表格摘自http://www.cnblogs.com/icejoywoo/archive/2012/02/22/2363709.html)

    2处是函数申明,我们在c/c++中需要实现

    4、用visual c++新建一个dll工程。test.h文件中包含#include <jni.h>,包含的jni.h存在于JDK安装目录下的include下面。需要将他们添加进来。

    Tools->Options->Directories,新建Directions。

    再就是用c/c++实现本地方法,注意.c/.cpp中的函数名必须和.h中的函数名一致

    下面是.cpp的代码

    #include "windows.h"
    #include "Test.h"
    #include "iostream.h"
    /*
    * Class: Test
    * Method: testPrint
    * Signature: (Ljava/lang/String;)V
    */
    JNIEXPORT void JNICALL Java_Test_testPrint(JNIEnv * env, jobject obj, jstring str){
    const char *msg;
    msg = env->GetStringUTFChars(str,0);
    cout<<"the msg is"<<endl;
    cout<<msg<<endl;
    env->ReleaseStringUTFChars(str,msg);
    }

    5、编译通过生成TestAgain.dll。将它复制到之前建的eclipse工程根目录下面

    6、回到eclipse界面,F5刷新工程,然后run。结果如下

    这样就实现了在Java中调用c/c++。

     

     

     

  • 相关阅读:
    GET请求和POST请求的本质区别
    go切片的Add与Del
    滚动到指定位置的问题
    promise---批量调用接口,等待所有的请求发完
    this argument
    html2canvas截图 下载图片
    数组合并去重
    vue项目踩坑
    关于java中的栈和堆
    用python实现一个最简单版本的mysql数据库连接池
  • 原文地址:https://www.cnblogs.com/cuglkb/p/5665882.html
Copyright © 2020-2023  润新知