Jni编程(一)内容简介以及helloworld
写在开端的话语:
从今天开始我将书写一系列的关于jni编程的从入门到熟练的博客(精通不敢说,哈哈),一个是为了记录自己的学习历程,怕自己忘记,另一个也是想把自己的学习成果向大家分享一下啊。当然学习这个之前你要有c/c++的基础才行(不会的话还是自己先学一下),要不然你会一脸懵逼。后面我会分享一些关于 jni实战的demo,包括jni处理gif动画,视频编解码,加水印等等(因为我是做Android开发的所以后面的实战主要还是以app的形式来学习 )。由于前面主要是学习jni的一些规范,因为Android stuido比较的耗内存(取决于电脑的性能),编译时间也慢,为了快速学习jni的规范,所以我们采用elipse+visual studio 编译处dll的方式 这也有利于我们快速的学习和调试。(windows 下面是 dll,Android下面so文件,其实原理都是一样的)每一篇博客尽量的短,俗话说,浓缩的才是精华,因为太长了看着也费劲,我写着也费劲,尽量写的简明扼要。
先学语法,语法学完再转到Android实战!!!
先学语法,语法学完再转到Android实战!!!
先学语法,语法学完再转到Android实战!!!
一、jni简介
●Java是跨平台的语言,但是在有些时候仍然是有需要调用本地代码(这些代码通常是由C/C++编写的)
●Sun公司提供的JNI是Java平台的一个功能强大的接口,这个JNI接口提供了Java与操作系统本地代码互相调用的功能。
二、JNIEnv ,jobject ,jclass
1. JNIEnv类实际代表了Java环境,通过这个JNIEnv* 指针,就可以对Java端的代码进行操作。例如,创建Java类的对象,调用Java对象的方法,获取Java对象的属性等等,JNIEnv的指针会被JNI传入到本地方法的实现两数中來对Java端的代码进行操作。
JNIEnv类中有很多函数用可以用如下所示其中:TYPE代表属性或者方法的类型(比如:int float double byte ......)
1.NewObject/NewString/New<TYPE>Array
2.Get/Set<TYPE>Field
3.Get/SetStatic<TYPE>Field
4.Call<TYPE>Method/CallStatic<TYPE>Method等许许多多的函数
2. jobject代表了在java端调用本地c/c++代码的那个类的一个实例(对象)。在修改和调用java端的属性和方法的时候,用jobject 作为参数,代表了修改了jobject所对应的java端的对象的属性和方法(具体理解可以参考下面的例子)
3. jclass : 为了能够在c/c++中使用java类JNI.h头文件中专门定义了jclass类型来表示java中的Class类
JNIEvn中规定可以用以下几个函数来取得jclass
1.jclass FindClass(const char* clsName) ;
2.jclass GetObjectClass(jobject obj);
3.jclass GetSuperClass(jclass obj);
三、编写第一个jni程序
1.elipse新建一个java工程Jni01代码如下:
package com.koimy;
public class Main {
public native void sayHello();
public static void main(String[] args) {
}
}
2.然后打开cmd命令行进入到elipse当前工程目录下的src目录 执行 javah -jni com.koimy.Main ( 即: javah -jni 完整类名)命令然后回车,这个命令是生成头文件如下图所示生成 com_koimy_Main.h头文件
3.打开visual studio 创建工程
如下所示
点击确定:
此时创建了一个空的c++工程 然后将jdk安装目录下的include文件夹下的 jni.h 和 win32文件夹下的jni_md.h拷贝到当前工程目录下,还有将在java工程中生成的 com_koimy_Main.h头文件也拷贝到 当前c++工程目录下
右键选择工程头文件->添加->现有项,找到拷贝的那几个头文件添加进来
然后选择源文件->右键->添加->新建项->c++文件(.cpp)->文件名(source.cpp)->确定
source.cpp 中的代码如下:就是在java端调用的时候才控制台打印下面一句话 (这里有一个坑就是无法引用com_koimy_Main。h这个头文件:可以这样设置 点击 :项目->属性->C/C++->附加包含目录:填写附加头文件所在目录 分号间隔多项)
#include<iostream>
#include"com_koimy_Main.h"
using namespace std;
JNIEXPORT void JNICALL Java_com_koimy_Main_sayHello (JNIEnv *env, jobject obj)
{
cout<<"This message is from JNI by C++!"<<endl;
}
然后点击visual studio 菜单栏上面的 项目->NativeCode属性 修改生成dll的 类型是32位的还是64位的默认是32位的。做不做这一步取决于你的计算机是32位的还是64位的我的是64位的所以修改配置如下:
4.然后编译c++项目会在 工程根目录下的x64文件夹下的Relaese文件夹下生成NativeCode.dll (64位)我的路径是D:\VC++\NativeCode\x64\Release 然后将这个路径拷贝到path环境变量下。
5.重启elipse (让elipse重新读取一下classpath环境变量)修改elipse工程中的代码如下:
package com.koimy;
public class Main {
int num = 123;
static {
System.loadLibrary("NativeCode");
}
public native void sayHello();
public static void main(String[] args) {
Main main = new Main();
main.sayHello();
}
}
最后elipse控制台成功打印了c++中写的代码
PS:欢迎加入我的qq群一起学习:239074811