1,mingw具体配置


配置环境变量:
打开:“我的电脑->属性->高级->环境变量->系统变量”编辑如下系统变量:
变量名 变量值
PATH C:\MinGW\bin;
LIBRARY_PATH C:\MinGW\lib
C_INCLUDEDE_PATH C:\MinGW\include
CPLUS_INCLUDE_PATH C:\MinGW\include\c++\3.4.2;C:\MinGW\include\c++\3.4.2\mingw32;C:\MinGW\include\c++\3.4.2\backward;C:\MinGW\include

盘符自己搞定吧…
201109161204582608.png



2,开始第一个JNI

1,JNI的原理图


201109161205055843.png


2,开始使用JNI



package kg.tom;

public class MyJni {
//使用JNI的关键字native
//这个关键字决定我们那些方法能在我们的C文件中使用
//只须声明,不必实现
public native void display();
public native double sum(double x,double y);

//这个是到时候调用我们写好的C文件
//现在用不上
//static {
// System.loadLibrary("sum");
//}


public static void main(String[] args) {
//到时候测试用方法现在用不上
//new MyJni().display();
//System.out.println(new MyJni().sum(2.0, 3.0));
}
}


然后,就是返回到我们的java基础了…将我们写好的类,转换成头文件

1,先把写好的类转换成.class文件


201109161205066465.png

2,把.class文件转换成头文件,成功的话就会在src目录下看到.h文件了


201109161205066814.png
打开后你会看到

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

#ifndef _Included_kg_tom_MyJni
#define _Included_kg_tom_MyJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: kg_tom_MyJni
* Method: display
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_kg_tom_MyJni_display
(JNIEnv *, jobject);

/*
* Class: kg_tom_MyJni
* Method: sum
* Signature: (DD)D
*/
JNIEXPORT jdouble JNICALL Java_kg_tom_MyJni_sum
(JNIEnv *, jobject, jdouble, jdouble);

#ifdef __cplusplus
}
#endif
#endif

native方法名称转换详解:[table=600][tr][td=1,1,201] 英语原文[/td][td=1,1,204] 我的理解…[/td][td=1,1,193] 例子[/td][/tr][tr][td=1,1,201]
the prefix Java_[/td][td=1,1,204] 转换后的native方法全部以Java_为前缀[/td][td=1,1,193] Java_kg_tom_MyJni_display[/td][/tr][tr][td=1,1,201]
a mangled fully-qualified class name[/td][td=1,1,204] 接着以类的全名标识(包名+类名)[/td][td=1,1,193] Java_kg_tom_MyJni_display[/td][/tr][tr][td=1,1,201]
  • an underscore (“_”) separator
[/td][td=1,1,204] 以下划线为分隔符(“_”)[/td][td=1,1,193] Java_kg_tom_MyJni_display[/td][/tr][tr][td=1,1,201] mangled method name[/td][td=1,1,204] 最后就是方法的名称[/td][td=1,1,193] Java_kg_tom_MyJni_display[/td][/tr][tr][td=1,1,201]
  • for overloaded native methods, two underscores (“__”) followed by the mangled argument signature
[/td][td=1,1,204] 这个理解不能:直译的话就是对已经读取过的native方法,用双下划线(“__”)标注[/td][td=1,1,193] 没找到[/td][/tr][/table]

3,就是写我们的C文件了



//必须的头文件jni.h
#include <jni.h>
//导入我们需要实现的本地方法
#include "kg_tom_MyJni.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_kg_tom_MyJni_display
(JNIEnv *env, jobject obj)
{
printf("Hello World tom!!");
return;
}

JNIEXPORT jdouble JNICALL Java_kg_tom_MyJni_sum
(JNIEnv *env, jobject obj, jdouble a, jdouble b)
{
return a + b;
}



4,windows下编译成dll文件,linux下编译成so文件.这里只说windows下的



1,java基础


找到我们的jdk文件夹,然后打开其中的include文件夹,就会看到一些头文件,看下关键的Jni.h头文件在不在,在的话,继续,不在
自行下载一个新的jdk…

2,把C文件编译成dll文件


我们这里使用mingw….你会用VC6也可以用VC6编译…
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -Id:/java/include –Id:/java/include/win32 -shared -o sum.dll java_sum_native.c[table=400][tr][td=1,1,200] 命令[/td][td=1,1,200] 简单介绍[/td][/tr][tr][td=1,1,200] -Wall -D_JNI_IMPLEMENTATION_[/td][td=1,1,200] 把我们的C文件编译成dll[/td][/tr][tr][td=1,1,200] -Wl,--kill-at [/td][td=1,1,200] 因为mingw默认是用@来进行分隔,会导致JNI机制不能读取,所以要删掉..
mingw官网解释[/td][/tr][tr][td=1,1,200] Id:/java/include –Id:/java/include/win32 [/td][td=1,1,200] 导入我们用的的jni需要的头文件…盘符,文件夹自己修改[/td][/tr][tr][td=1,1,200] -shared -o[/td][td=1,1,200] 输出配置,第一个参数为我们输出的名字(随便起),第二个参数为我们的C文件(随便起)[/td][/tr][tr][td=1,1,200] [/td][td=1,1,200] [/td][/tr][/table]

1626883380167-1.jpg
没出什么提示的话就是成功的了…

4,运行我们的JNI



1,用eclipse的话,我们把编译好的dll放到项目根目录,注意不是代码根目录



//把刚才注释的地方删掉..
//这就是必须的,用来读取我们写好的C语言编译好的dll,后缀是系统自己辨认…千万不要自己写
static {
System.loadLibrary("sum");
}
//mian方法中
//用底层c代码实现输出..呵呵~~
new MyJni().display();
//用c计算会不会快点呢..呵呵~
System.out.println(new MyJni().sum(2.0, 3.0));

输出结果
201109161205313567.png
貌似java本身的输出,优先级比较高??

2,补充一下:


1,我们要运行我们编译的C文件,是与我们创建的类是必须一起存在,
例如:我把MyJni.java删掉,然后另起一个Hello.java能不能直接调用dll中的方法呢?那是肯定不行的..因为,jni需要类名来进行查找

手机发帖。。十分蛋疼啊
有什么不对中午回家改


原帖地址:http://www.cnblogs.com/youxilua/archive/2011/09/16/2178554.html