《Android进阶》之第一篇 在Java中调用C库函数

时间:2023-03-08 17:34:35

在Java代码中通过JNI调用C函数的步骤如下:

第一步:编写Java代码

 class HelloJNI{
native void printHello();
native void printString(String str); static {System.loadLibrary("hellojni");} public static void main(String args[]) {
HelloJNI myJNI = new HelloJNI(); myJNI.printHello();
myJNI.printString("Hello World from c fun"); } }

第二步: 编译Java代码

    javac HelloJNI.java   生成HelloJNI.class文件

第三步: 生成C语言头文件

    javah HelloJNI   生成HelloJNI.h头文件    

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */ #ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: printHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printHello
(JNIEnv *, jobject); /*
* Class: HelloJNI
* Method: printString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_printString
(JNIEnv *, jobject, jstring); #ifdef __cplusplus
}
#endif
#endif

第四步: 编写C代码

  要注意c代码必须得依照上面头文件的方式编写,和普通的c函数有区别

 #include"HelloJNI.h"
#include<stdio.h> JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj) {
printf("Hello World!\n");
return;
} JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv * env, jobject obj, jstring string) {
const char *str = (*env)->GetStringUTFChars(env,string,);
printf("%s!\n",str);
return;
}

第五步: 生成C共享库

  CodeBlocks下:

   File - New - Project - Shared library - Go

因为HelloJNI.h中有这样的一句#include <jni.h>,标准的库文件下是没有这个文件的,但这个文件可以在JDK的安装目录下面找到

《Android进阶》之第一篇  在Java中调用C库函数

为了能够顺利编译,需要把相应文件复制到C编译器的头文件存放处,像下面这样:

《Android进阶》之第一篇  在Java中调用C库函数

编译生成C共享库文件:

《Android进阶》之第一篇  在Java中调用C库函数

不过CodeBlocks默认生成的文件前面加了前缀lib,需要手动去掉,但运行是还是出了问题:

 D:\hixin\C>java HelloJNI
Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\hixin\C\hellojni.d
ll: Can't load IA 32-bit .dll on a AMD 64-bit platform
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.loadLibrary0(Unknown Source)
at java.lang.System.loadLibrary(Unknown Source)
at HelloJNI.<clinit>(HelloJNI.java:)

大意是生成的dll不是64位的,看了网上最新版的vs似乎是可以生成64位dll,算啦不纠结这个啦