您的位置:首页 > 编程语言 > C语言/C++

JNI编程Demo----Java程序调用C&C++编译好的库文件

2017-07-21 17:03 531 查看
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。下面用一个Demo实现通过JNI,Java如何调用C&C++的库文件(Windows下是dll文件,Linux下是so文件)。

本文在Windows下实现,因此调用的是dll文件,期间也会说明linux下调用so文件有什么不同之处,环境如下:

- 操作系统:Win10 Pro

- JDK:1.7(1.8也完全ok)

- IDE:Jetbrains IDEA 2016.3 Community

一、安装GCC环境

Windows下,一般选择安装MinGW,下载地址:下载地址,安装好后,将MinGW安装目录下的bin目录加入PATH中,然后打开命令行,输入gcc -v,出现如下信息即证明安装完成:



二、JNI Demo

首先用IDEA创建一个Java工程,在src目录下创建一个包,包名为cn.hust.demo,如图:



在该包下编写类TestAdd,我们要实现的功能是两个数相加:

package cn.hust.demo;

// Created by LCJ on 2017.7.21.

public class TestAdd {

static {
System.loadLibrary("Add");
}

private native int add(int a, int b);

public static void main(String[] args) {
int c = new TestAdd().add(3, 4);
System.out.println("Result is: " + c);
}
}


方法System.loadLibrary()用来加载dll(windows)或so(Linux)库,只需名称即可,无需加入文件名后缀(.dll或.so)。native关键字将函数add(int a, int b)声明为本地函数,由C/C++实现。具体的实现就在Add.dll(Windows平台)或libAdd.so(Linux平台)中。注意,在Linux平台下,so文件前面要有“lib”前缀(但是System.loadLibrary()的参数仍然和Windows下一样,不用带“lib”),否则会找不到库文件。

生成头文件

首先将TestAdd.java编译一下,出现TestAdd.class:



然后配置生成头文件的命令:

File–>Settings–>Tools–>External Tools,点击右边的“+”号,如下填写:



Name为“Generate Header File”,上图中Tool Settings部分的填写:

Program:
$JDKPath$/bin/javah


Parameters:
-jni -classpath $OutputPath$ -d ./jni $FileClass$


Working Dictionary:
$ProjectFileDir$


如此配置好后,在TestAdd.java文件上右键,选择External tools–>Generate Header File:



即生成了头文件如下:



代码如下:

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

#ifndef _Included_cn_hust_demo_TestAdd
#define _Included_cn_hust_demo_TestAdd
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     cn_hust_demo_TestAdd
* Method:    add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_cn_hust_demo_TestAdd_add
(JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif


在此代码中,函数命名为Java_<包>_<类名>_<函数名>,参数中除前两个参数外,后面两个是add函数的参数类型,jint对应int型。

编写C语言文件

在jni目录下编写add.c文件:



代码:

#include <jni.h>
#include <stdio.h>
#include "cn_hust_demo_TestAdd.h"

JNIEXPORT jint JNICALL Java_cn_hust_demo_TestAdd_add(JNIEnv *env, jobject o, jint a, jint b)
{
jint c = a + b;
printf("The sum of %d + %d is: %d", a, b, c);
return c;
}


编译C语言文件,生成dll库

仍然同生成头文件一样,用IDEA的external tools一键生成dll文件。因此打开external tool配置界面,点击“+”号,创建一个名为“Generate DLL”(如果是Linux环境下,你就命名为“Generate SO”)的tool:



具体配置如下:

Program:
D:\Program Files\MinGW\mingw64\bin\gcc.exe
即你的gcc目录,Linux下也同样是gcc路径

Parameters:
-Wl,--add-stdcall-alias -I"$JDKPath$\include" -I"$JDKPath$\include\win32" -shared -o ./lib/$FileNameWithoutExtension$.dll ./jni/$FileNameWithoutExtension$.c
注意,如果是Linux环境下,win32要改成linux,dll文件的文件名也要改,前面要加上lib前缀,同时是so文件而非dll文件,命令细节也要更改,最终如此:
-I"$JDKPath$\include" -I"$JDKPath$\include\linux" -fPIC -shared -o ./lib/lib$FileNameWithoutExtension$.so ./jni/$FileNameWithoutExtension$.c


Working dictionary:
$ProjectFileDir$


配置好后,在工作目录下新建lib文件夹,然后右键Add.c,选择external tools中的“Generate DLL”,在lib目录下生成DLL文件:





运行Java程序,得出结果

此时,运行一开始的java程序会报错找不到库文件:



这时,需要在运行参数中配置如下:



将VM options中加入:

-Djava.library.path=I:\IDEAWorkspace\JNI\TestJNIDemo\lib


即library path指向DLL文件所在目录即可。

此时再运行java程序,即得出正确结果:



三、附注

本文展示了生成头文件、写C语言程序和生成库文件的全过程Demo,一般情况下,是直接拿到库文件进行调用的,因此前面的过程可以略去,只需知道该库文件哪些函数可以调用,直接用Java进行调用即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: