01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用
1 什么是JNI
JNI Java本地开发接口 |
JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(C/C++) 通过这个协议,java代码就可以调用外部的C/C++代码,外部的C/C++代码也可以调用Java代码。 |
2 为什么用JNI
1 JNI扩展了java虚拟机的能力,驱动开发(wifi-hotspot)2.3无线热点共享 2 Native code效率高,数学运算,实时渲染的游戏上,音视频处理(极品飞车),opengl,ffmpeg 3 复用代码(文件压缩,人脸识别) 4 特殊的业务场景 |
3 怎么用JNI
1 C/C++语言 2 掌握java ini流程 3 NDK(native develop kits) |
5 配置cygwin64的环境变量的方式是编写\Cygwin\etc\profile,将ndk的路径配置到path里面,截图如下:
打开Cygwin输入:Make –v,结果如下:
显示出来GNI Make的版本,说明我们的cygwin模拟的Linux编辑环境模拟成功。
输入ndk-build,出现以下结果:
显示出上面的效果,说明环境变量已经配置好了。
6 同样可以将这个变量配置到windows下的环境变量中:配置如下:
进入CMD命令行窗口中,如果出现以下结果,说明配置成功:
当配置了第6步之后,若cygwin没有配置成功时,也可以在window中的cmd命令行中使用ndk-build.
7 jni中的数据类型(后面是Java中的类型,左边是C语言中的类型):
#ifdef HAVE_INTTYPES_H # include <inttypes.h> /* C99 */ typedef uint8_t jboolean; /* unsigned 8 bits */ typedef int8_t jbyte; /* signed 8 bits */ typedef uint16_t jchar; /* unsigned 16 bits */ typedef int16_t jshort; /* signed 16 bits */ typedef int32_t jint; /* signed 32 bits */ typedef int64_t jlong; /* signed 64 bits */ typedef float jfloat; /* 32-bit IEEE 754 */ typedef double jdouble; /* 64-bit IEEE 754 */ #else typedef unsigned char jboolean; /* unsigned 8 bits */ typedef signed char jbyte; /* signed 8 bits */ typedef unsigned short jchar; /* unsigned 16 bits */ typedef short jshort; /* signed 16 bits */ typedef int jint; /* signed 32 bits */ typedef long long jlong; /* signed 64 bits */ typedef float jfloat; /* 32-bit IEEE 754 */ typedef double jdouble; /* 64-bit IEEE 754 */ #endif /* "cardinal indices and sizes" */ typedef jint jsize; |
8 案例效果(下面的土司是调用C语言代码显示的):
接下来编写案例,使用java代码调用C代码,创建项目helloworldformc,代码结构如下:
其中libs下的内容如下:
9 编写MainActivity,代码如下:
package com.example.helloworldformc; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { // 1 定义一个c方法的接口 相当于在java代码中定义了一个接口 //接口的实现方法是C语言实现的 public native String helloWorldFromC(); // 变态命名 // 5 步在java代码中 引入库函数 static{ System.loadLibrary("hello");// 注意事项 去掉前面的lib 后面的.so } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View view){ // 弹出一个土司 土司的内容 是c代码写出来 // 第6步 Toast.makeText(getApplicationContext(), helloWorldFromC(), 0).show(); } } |
10 在项目下创建一个jni目录(这个是必须的),开始编写Hello.c,代码如下:
#include <stdio.h> #include <jni.h> /* * 对应的是:public native String helloWorldFromC(){} * jstring:表示的是返回的是String类型的 * 函数名称规则是:Java_包名_类名_方法名。 * * 注意:包名之间的"."在下面要变成下划线 */ jstring Java_com_example_helloworldformc_MainActivity_helloWorldFromC(JNIEnv* env,jobject obj) { //2步 实现C代码 //返回一个java String类型的字符串,使用一下函数 //jstring (*NewStringUTF)(JNIEnv*, const char*); //(*env) 相当于 JNINativeInterface* JNIEnv //*(*env) 相当于 JNINativeInterface //可以通过下面两种方式返回参数 //return (**env).NewStringUTF(env,"helloworldfromc"); return (*env)->NewStringUTF(env,"helloworldfromc"); //android.mk 告诉编译器 如何把C代码打包成函数库 //3 生成.mk文件 //4 步 把C代码 打包成函数库 } /*这里JNIEXPORT表示的是通过工具生成的,这时候也可以将JNIEXPORT去掉*/ JNIEXPORT jstring JNICALL Java_com_example_helloworldformc_MainActivity_hello_1world_1from_1c (JNIEnv * env, jobject obj){ } |
注意:上面的这个源文件的类名也可以通过javah命令生成,生成过程如下:
(1) 如果JDK使用的是1.6,使用javah命令前要到达:项目目录\bin\classes目录下 (2) 如果JDK使用的是1.7,使用javah命令前要达到:项目目录\bin\src目录下: 例如(我使用的是JDK1.7): 在项目中生成.h: |
11 Android.mk文件的内容如下:
#一个Android.mk文件必须下面这个变量开头,它用于定位 #它用于定位你的源文件,my-dir这个宏是构件系统提供的, #它用于返回当前目录的路径(这个目录包含Android.mk它自己) LOCAL_PATH := $(call my-dir) #CLEAR_VARS也是build system构件系统提供的,指定到一个指定的GNU Makefile文件 #这个Makefile文件帮你去清除一些LOCAL_XXX变量(比如:LOCAL_MODULE,LOCAL_SRC_FILES #,LOCAL_STATIC_LIBRARIES.等等...),除了LOCAL_PATH. include $(CLEAR_VARS) #LOCAL_MODULE变量必须在你的Android.mk文件中定义。名称必须唯一 #并且不能包含一些空格,要注意的是构件系统会自动的添加适当的前缀和前缀 #换一句话说,一个命名为"foo"的共享库模块,会被生成"libfoo.so"文件。 #重要提示:如果你定义的模块名称是"libfoo",构建系统将不会添加"lib"前缀, #并且也会生成"libfoo.so"文件。 LOCAL_MODULE := hello #LOCAL_SRC_FILES变量必须包含一个C或者C++的源文件集合,这些文件最终会被用于 #生成一个module,注意的是,这里不应该有头文件和包含文件,因为构件系统自动为您 #添加这些文件,只需要列出源文件就行了。 #注意:默认的C++源文件的后缀名是.cpp,同样你也可以通过LOCAL_CPP_EXTENSION来自定义 #CPP的后缀名(例如:".cxx"可以,"cxx"不可以) LOCAL_SRC_FILES := Hello.c include $(BUILD_SHARED_LIBRARY) |
12 接下来使用cygwin,使用ndk-build来编译程序
(1)、如想将c变成.so的库,需要使用ndk-build命令 (2)、将路径路径切换到工程目录下。 (3)、然后执行ndk-build这个操作(这个操作直接指定到项目路径下就可以了) 注意:在使用这个ndk-build功能之前,需要有Android.mk文件(告诉编译器,如何将C代码打包成函数库。具体的Android.mk怎么使用可以看ndk中的Android.html文档) |
01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用的更多相关文章
- windows和linux环境下java调用C++代码-JNI技术
最近部门做安卓移动开发的需要调C++的代码,困难重重,最后任务交给了我,查找相关资料,没有一个教程能把不同环境(windows,linux)下怎么调用说明白的,自己在实现的过程中踩了几个坑,在这里总结 ...
- 通过JNI实现java调用C代码和C代码调用java的代码
一.java调用C代码 1)java中需要声明调用的函数,也就是native方法,并通过System.LoadLibrary来调用dll或者so(C代码).实例代码如下: public class H ...
- JNI Java调用C代码 示例
Activity public class MainActivity extends ListActivity { static { System.loadLibrary(&q ...
- 1.JAVA中使用JNI调用C++代码学习笔记
Java 之JNI编程1.什么是JNI? JNI:(Java Natibe Inetrface)缩写. 2.为什么要学习JNI? Java 是跨平台的语言,但是在有些时候仍然是有需要调用本地代码 ( ...
- Java调用C++类库--JNI
JNI是Java平台中的一个重要的功能,这里我把我做的Demo总结一下,分享一下,我会把每个步骤尽量的详细的展现出来. 这里我就不讲解JNI的原理了,google,百度一下,到处都是 好了,直接来讲步 ...
- AndroidStudio如何配置NDK/JNI开发环境
参考文章: http://www.th7.cn/Program/Android/201509/550864.shtml http://www.open-open.com/lib/view/open14 ...
- JNI环境变量——JNIEnv*的使用 &&配置jd环境变量
如果没有配置环境变量,先配置环境变量,如下: 1.右键我的电脑——高级——环境变量——下面的系统变量 2.选择[新建系统变量]--弹出“新建系统变量”对话框,在“变量名”文本框输入“JAVA_HO ...
- Android使用JNI(从java调用本地函数)
当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...
- Android JNI之JAVA调用C/C++层
转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5929996.html 一.java调用本地函数的开发步骤: 1.编写本地方法的类(可以说是用来叙述本地方法的类 ...
随机推荐
- OpenCV RGB2LAB执行效率测试
代码 #include <iostream> #include <vector> #include <opencv2/opencv.hpp> #define ERR ...
- 全面剖析Redis Cluster原理和应用
全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最 ...
- proc文件系统探索 之 根目录下的文件[1]
2.1根目录下的文件2.1.1lock文件内核锁,记录与被打开的文件有关的锁信息. 该文件显示当前被内核锁定的文件.该文件包含的内容是内核调试数据,根据使用的系统的这些数据会变化很大.一个/proc/ ...
- Android简易实战教程--第四十五话《几种对话框》
Android中提供了各种原生的对话框,在使用简单的功能的时候,还不比考虑自定义,使用原生的也能完成功能.本篇简单小案例就介绍三种对话框. 还是直接上代码吧: 布局中三个点击事件的按钮: <Li ...
- Linux 高性能服务器编程——多线程编程
问题聚焦: 在简单地介绍线程的基本知识之后,主要讨论三个方面的内容: 1 创建线程和结束线程: 2 读取和设置线程属性: 3 线程同步方式:POSIX信号量,互斥锁和条件变量 ...
- 文件自动备份和同步bypy和syncthing
http://blog.csdn.net/pipisorry/article/details/52464402 Linux定时备份数据到百度云盘 sudo pip3 install requestss ...
- Erlang edoc 多级目录出错
Erlang edoc 多级目录出错使用rebar doc来生成项目文档.但是当erl源文件目录src下建立子目录,并新建erlang文件后,就无法生成文档. 例如,新建 src/tttt/, 并添加 ...
- iOS10软件崩溃 Xcode8崩溃 打印/字体等问题汇总 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博!iOS开发者交流QQ群: 446310206 [1].Xcode8代码出现ubsystem: com.apple.U ...
- 【IOS 开发】Objective - C 面向对象高级特性 - 包装类 | 类处理 | 类别 | 扩展 | 协议 | 委托 | 异常处理 | 反射
一. Objective-C 对象简单处理 1. 包装类 (1) 包装类简介 NSValue 和 NSNumber : -- 通用包装类 NSValue : NSValue 包装单个 short, i ...
- Ext JS 6开发实例(三) :主界面设计
在上文中,已经将CMD创建的应用程序导入到项目里了,而且也看到默认的主界面了,今天的主要工作就是修改这个主界面,以符合项目的需要.除了设计主界面,还有一些其他的东西需要配置一下. 添加本地化包 打开a ...