JNI:从Java程序中调用C函数

今天看了《core java卷二》的第十二章,在自己写代码的时候还是踩到了一些坑,因此在这里记录一下。

1、创建java类,建议不要加包名,省的后面找不到类(我之前加了包名,导致后面各种找不到或无法加载主类。。)


public class HelloNative {

    public static native void greeting();

    static {

        System.loadLibrary("hellonative");

    }

    public static void main(String[] args) {

        HelloNative.greeting();

    }

}

greeting方法就是我们要用C语言实现的方法。System.loadLibrary用于加载动态链接库。

2、编译这个类。
javac HelloNative.java

3、调用javah来生成头文件HelloNative.h
javah -jni HelloNative

HelloNative.h:

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

#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloNative
 * Method:    greeting
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

4、在HelloNative.c中给出函数的实现代码。
HelloNative.c

#include "HelloNative.h"
#include 

JNIEXPORT void JNICALL Java_HelloNative_greeting(JNIEnv * env, jclass jcl){
    printf("Hello Native !\n");
    return;
}

5、将C代码编译到动态链接库中。

gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/include HelloNative.c -o libhellonative.jnilib

其中,JDK的目录各位读者请自行调整。
gcc的-I选项指定寻找头文件的目录,主要是由于HelloNative.h中有一行
#include ,而jni.h这个文件就在
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/include目录下面。
同理,由于jni.h里面有一行#include "jni_md.h"
如果/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/include目录下面没有jni_md.h,则会报下面错误:

Cannot open include file: 'jni_md.h': No such file or directory

这时候把jni_md.h拷贝到
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/include
目录里面即可。
gcc编译成功后,就会得到libhellonative.jnilib这个文件。
在HelloNative.java文件中,有一行代码:

System.loadLibrary("hellonative");

就是用来加载libhellonative.jnilib的。
注意:在执行gcc命令时,-o libhellonative.jnilib中,hellonative前面的lib不可以缺少!!!(我就因为忽略了这个,网上查了好久的才发现,都是泪啊。。)
否则,会报no XXX in java.library.path错误。

6、执行java HelloNative,打印Hello Native !,调用成功~

你可能感兴趣的:(JNI:从Java程序中调用C函数)