在Java代碼中通過JNI調用C函數的步驟如下:
第一步:編寫Java代碼
1 class HelloJNI{ 2 native void printHello(); 3 native void printString(String str); 4 5 static {System.loadLibrary("hellojni");} 6 7 public static void main(String args[]) { 8 HelloJNI myJNI = new HelloJNI(); 9 10 myJNI.printHello(); 11 myJNI.printString("Hello World from c fun"); 12 13 } 14 15 }
第二步: 編譯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函數有區別
1 #include"HelloJNI.h" 2 #include<stdio.h> 3 4 JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj) { 5 printf("Hello World!\n"); 6 return; 7 } 8 9 JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv * env, jobject obj, jstring string) { 10 const char *str = (*env)->GetStringUTFChars(env,string,0); 11 printf("%s!\n",str); 12 return; 13 }
第五步: 生成C共享庫
CodeBlocks下:
File - New - Project - Shared library - Go
因為HelloJNI.h中有這樣的一句#include <jni.h>,標准的庫文件下是沒有這個文件的,但這個文件可以在JDK的安裝目錄下面找到
為了能夠順利編譯,需要把相應文件復制到C編譯器的頭文件存放處,像下面這樣:
編譯生成C共享庫文件:
不過CodeBlocks默認生成的文件前面加了前綴lib,需要手動去掉,但運行是還是出了問題:
1 D:\hixin\C>java HelloJNI 2 Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\hixin\C\hellojni.d 3 ll: Can't load IA 32-bit .dll on a AMD 64-bit platform 4 at java.lang.ClassLoader$NativeLibrary.load(Native Method) 5 at java.lang.ClassLoader.loadLibrary0(Unknown Source) 6 at java.lang.ClassLoader.loadLibrary(Unknown Source) 7 at java.lang.Runtime.loadLibrary0(Unknown Source) 8 at java.lang.System.loadLibrary(Unknown Source) 9 at HelloJNI.<clinit>(HelloJNI.java:5)
大意是生成的dll不是64位的,看了網上最新版的vs似乎是可以生成64位dll,算啦不糾結這個啦