最近需要用到JNI,所以抽时间学习了下,对于我这个N年没用过C/C++的,从没用过VS2005的java码农来说,真不容易,编译个dll都遇到莫名其妙的问题~~
下面就来一步一步开始JNI之路。
一、通过java类得到.h头文件
首先,我们写一个java类,声明几个native方法
package jni.test;public class JNIWrapper { public native void display(); public native double sum(double x, double y); public native double divide(double x, double y);}
然后,依次执行如下命令,依次得到class和.h文件
编译class...\src>javac jni\test\JNIWrapper.java生成头文件...\src>javah jni.test.JNIWrapper
到这里就得到了一个名为“jni_test_JNIWrapper.h”的头文件,其内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */#include/* Header for class jni_test_JNIWrapper */#ifndef _Included_jni_test_JNIWrapper#define _Included_jni_test_JNIWrapper#ifdef __cplusplusextern "C" {#endif/* * Class: jni_test_JNIWrapper * Method: display * Signature: ()V */JNIEXPORT void JNICALL Java_jni_test_JNIWrapper_display (JNIEnv *, jobject);/* * Class: jni_test_JNIWrapper * Method: sum * Signature: (DD)D */JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_sum (JNIEnv *, jobject, jdouble, jdouble);/* * Class: jni_test_JNIWrapper * Method: divide * Signature: (DD)D */JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_divide (JNIEnv *, jobject, jdouble, jdouble);#ifdef __cplusplus}#endif#endif
经过转换之后,方法名、变量类型什么的都变了,不过都挺有规律的:Java_包名+类名(点都换成下划线)_方法名
二、创建一个dll工程
首先,在VS2005中,点击新建,出现下图
输入Name之后,点击[OK],出现下图:
选择dll,点击finish完成即可创建dll工程
三、编写C/C++代码,生成dll
将步骤一种生成的头文件拷贝到工程中“Header Files”目录下,然后新建一个cpp文件,或者直接在默认生成的jnitest.cpp中编码
// jnitest.cpp : Defines the entry point for the DLL application.//#include "stdafx.h"#include "jni_test_JNIWrapper.h"#include//一定要加上这个#ifdef _MANAGED#pragma managed(push, off)#endifBOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ return TRUE;}#ifdef _MANAGED#pragma managed(pop)#endifJNIEXPORT void JNICALL Java_jni_test_JNIWrapper_display (JNIEnv *env, jobject obj){ printf("Hello World,JNI!\n"); return;}/** Class: jni_test_JNIWrapper* Method: sum* Signature: (DD)D*/JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_sum (JNIEnv *env, jobject obj, jdouble a, jdouble b){ return a + b;}JNIEXPORT jdouble JNICALL Java_jni_test_JNIWrapper_divide(JNIEnv *env, jobject obj, jdouble a, jdouble b){ return a/b;}
然后我们就可以开始编译了。
如果提示找不到“jni.h”,只需要做如下操作即可解决:
在%JAVA_HOME%\include\下找到 jni.h,在%JAVA_HOME%\include\win32\下找到jni_md.h和jawt_md.h把他们复制到“Visual Studio目录\VC\include\”下
四、继续完成Java代码调用dll
将步骤三得到的jnitest.dll放到java工程的根目录,注意是java项目的根目录,不是src目录
写个test方法测试下
package jni.test;public class JNITest { static { System.loadLibrary("jnitest"); } public static void main(String[] args) { JNIWrapper wrapper = new JNIWrapper(); wrapper.display(); System.out.println(wrapper.sum(1.0, 9.9999)); System.out.println(wrapper.divide(8.4, 2.4)); }}
不过,多数情况下,我们会把System.loadLibrary("jnitest")放在JNIWrapper中,即,
package jni.test;public class JNIWrapper { static { System.loadLibrary("jnitest"); } public native void display(); public native double sum(double x, double y); public native double divide(double x, double y);}
运行一下,输入结果为
10.99993.5000000000000004Hello World,JNI!
不知道打印“Hello World,JNI!”怎么最后执行~奇怪~
到这里,整个JNI调用过程就over了~~
不过还有类型转换什么的,以后再整理了....
推荐资料: