JNI学习笔记——JAVA调用C

Demo

从最简单的HelloWorld开始,理解JNI大概的步骤。

第一步 构建JAVA工程

Eclipse中,新建TestJNI的JAVA工程,自己建包名、类名之类的。
在该类中定义几个native方法,并定义好需要的返回值类型和函数名以及参数列表。
JNI学习笔记——JAVA调用C_第1张图片

第二步 生成JNI调用的C头文件

找到该工程的目录,Eclipse中一般都会自动编译生成class文件,我们需要使用的是class文件,若没用请在eclipse中编译一下。
目录结构如下:
JNI学习笔记——JAVA调用C_第2张图片
bin/目录下存放的是class文件,进入bin目录,在CMD中我们使用javah 包名.类名生成供C实现的JNI的头文件。
JNI学习笔记——JAVA调用C_第3张图片
完成这一步后,在bin目录下会生成包名_类名.h文件,这就是C/C++使用的头文件,剪切出来。
JNI学习笔记——JAVA调用C_第4张图片

第三步 新建VS工程

使用VS2015新建C++“Win32控制台应用程序”,新建设置中勾选如下图:
①类型选择“DLL”②附加选项选择“空项目”
JNI学习笔记——JAVA调用C_第5张图片

第四步 添加依赖

依赖共有三个文件:
①刚才生成的h文件②JDK目录/include/jni.h③JDK目录/inlude/win32/jin_md.h
VS工程JNI的依赖关系有两种方式可供选择。

1 使用包含库的形式

JNI学习笔记——JAVA调用C_第6张图片
JNI学习笔记——JAVA调用C_第7张图片

2 使用头文件添加现有项的形式

头文件直接右键添加现有项,jni.h和jni_md.h文件分别在JDK/include以及其子目录win32下,添加即可。
若包含头文件出错,<>改成""即可。

第五步 实现头文件

进入我们自己的头文件,头文件中是方法声明,我们在cpp文件中定义该函数就行了。参数列表中可以加入自己想要的形参名。
JNI学习笔记——JAVA调用C_第8张图片
实现完成后,点击最上面的生成,生成解决方案。
在工程目录/x64(32)/Debug(Release)/下,会有工程名.dll,这个就是我们JAVA所使用的动态链接库文件。

为JAVA工程添加库文件

首先先建立测试类,去加载库文件,并调用C/C++中实现的方法。
加载库文件有两种方式。

load方式

System.load(“带后缀的绝对路径”);这种方法采用绝对路径的形式。
优势:使用绝对路径,路径清晰。
弊端:若加载库文件有其他的依赖关系,则先通过默认Path去加载依赖的库文件,若不存在,则会调用失败。
参考链接:http://blog.csdn.net/u012525096/article/details/77947844

loadLibrary方式

System.loadLibrary(“库文件名,不带后缀”)
该方法从java.library.path只想的目录加载库文件。
该路径可通过System.getProperty("java.library.path");获取。
默认情况下,在Windows平台下,该值包含如下位置:
1)和jre相关的一些目录
2)程序当前目录
3)Windows目录
4)系统目录(system32)
5)系统环境变量path指定目录
优势:只要文件放在系统Path路径中,即可加载。

源码

头文件生成类

public class Test {
    public native String returnHelloWorldUpcase(String string);
    public native void sayHelloWorld();
}

测试类

public class Main {
    public static void main(String args[]) {
        System.loadLibrary("TestJNI1");
        Test test=new Test();
        test.sayHelloWorld();
        System.out.println(test.returnHelloWorldUpcase("ABC"));

    }
}

C++JNI头文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_shen_Test */

#ifndef _Included_com_shen_Test
#define _Included_com_shen_Test
#ifdef __cplusplus
extern "C" {
#endif
    /*
    * Class:     com_shen_Test
    * Method:    returnHelloWorldUpcase
    * Signature: (Ljava/lang/String;)Ljava/lang/String;
    */
    JNIEXPORT jstring JNICALL Java_com_shen_Test_returnHelloWorldUpcase
    (JNIEnv *, jobject, jstring);

    /*
    * Class:     com_shen_Test
    * Method:    sayHelloWorld
    * Signature: ()V
    */
    JNIEXPORT void JNICALL Java_com_shen_Test_sayHelloWorld
    (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

C++实现

#include "com_shen_Test.h"
#include 

JNIEXPORT jstring JNICALL Java_com_shen_Test_returnHelloWorldUpcase
(JNIEnv *, jobject, jstring str) {
    return str;
}
JNIEXPORT void JNICALL Java_com_shen_Test_sayHelloWorld
(JNIEnv *, jobject) {
    printf_s("Hello World");
}

你可能感兴趣的:(java,jni,jni,java)