JNI Java调用C代码 示例
Activity
public class MainActivity extends ListActivity {static {System.loadLibrary("hello");// 在java代码中引入libs目录下的库函数,文件名为【libhello.so】。注意,引入时的文件名要去掉前面的lib和后面的.soSystem.loadLibrary("hellocpp");}private TextView tv_info;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);String[] array = { "调用C中的无参方法,返回一个字符串", //"调用C中的有参方法,返回处理1+2后的值",//"对字符串进行处理", //"对int数组进行处理",//"调用C++中的无参方法,返回一个字符串", };tv_info = new TextView(this);tv_info.setTextColor(Color.BLUE);tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);tv_info.setPadding(20, 10, 20, 10);getListView().addFooterView(tv_info);setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>(Arrays.asList(array))));}@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {switch (position) {case 0:String stringFromC = MyNativeMethods.getInstance().helloFromC();tv_info.setText(stringFromC);break;case 1:int intFromC = MyNativeMethods.getInstance().passwordFromC(1, 2);tv_info.setText(intFromC + "");break;case 2:tv_info.setText(MyNativeMethods.getInstance().encodeFromC("abc123", 1));break;case 3:int array[] = MyNativeMethods.getInstance().intMethod(new int[] { 1, 2, 3, });tv_info.setText(Arrays.toString(array));break;case 4:tv_info.setText(MyNativeMethods.getInstance().helloFromCPP());break;}}}
本地方法
/** 存放native方法的类 */public class MyNativeMethods {/**返回一个字符串*/public native String helloFromC();/**返回int类型计算后的结果*/public native int passwordFromC(int x, int y);/**对给定字符串进行处理,模拟加密运算*/public native String encodeFromC(String text, int length);/**给c代码传递int数组,让c代码给这个数组进行操作;模拟多媒体解码*/public native int[] intMethod(int[] iNum);/**c++中的方法*/public native String helloFromCPP();//******************************************************************************************private static MyNativeMethods mEmployee;private MyNativeMethods() {}public static MyNativeMethods getInstance() {if (mEmployee == null) {mEmployee = new MyNativeMethods();}return mEmployee;}}
c文件
#include <stdio.h>#include <stdlib.h>#include <jni.h>//必须添加的头文件#include <string.h>#include "com_bqt_hellofromc_MyNativeMethods.h"//引入生成的头文件,注意要把此文件放在jni文件夹中,src目录下的此文件不需要了//在C中使用log,除在此声明外,还需在Android.mk文件中增加【LOCAL_LDLIBS += -llog】#include <android/log.h>//引入log头文件#define LOG_TAG "bqt"// 这个是自定义的LOG的标识//定义一些输出的LOG函数#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG ,__VA_ARGS__) // 定义LOGD类型#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG ,__VA_ARGS__) // 定义LOGI类型#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG ,__VA_ARGS__) // 定义LOGW类型#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG ,__VA_ARGS__) // 定义LOGE类型#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG ,__VA_ARGS__) // 定义LOGF类型//******************************************************************************************【1】返回一个字符串JNIEXPORT jstring JNICALL Java_com_bqt_hellofromc_MyNativeMethods_helloFromC(JNIEnv *env, jobject obj) {//写成【JNIEnv * env】或【JNIEnv *env】或【JNIEnv*env】都可以。【返回值】【方法名】【参数列表】返回值类型jstring就是java中的stringchar* cstr = "hello from c"; // char* 在c中可用来表示一个字符串。注意,这里绝对不能有中文jstring jstr = (*env)->NewStringUTF(env, cstr);return jstr;}//******************************************************************************************【2】返回int类型计算后的结果JNIEXPORT jint JNICALL Java_com_bqt_hellofromc_MyNativeMethods_passwordFromC(JNIEnv * env, jobject obj, jint a, jint b) {return a + b + 10000; //c中的int占用字节数在不同环境下可能不同,可能是0-65535,所以,稍微大一点的数(十万级别)都得用double}//******************************************************************************************【3】对给定字符串进行处理,模拟加密运算JNIEXPORT jstring JNICALL Java_com_bqt_hellofromc_MyNativeMethods_encodeFromC(JNIEnv * env, jobject obj, jstring passwd, jint length) {//char* cstr = Jstring2CStr2(env, passwd); //将java的字符串转化为c语言。卧槽这方法编译不通过,估计是因为找不到一些库之类的东西的原因!// int i = 0;// for (i = 0; i < length; i++) {// *(cstr + i) += 1; //给C语言字符加1// }char* cstr = "abc";return (*env)->NewStringUTF(env, cstr); //将c语言字符串转化为java字符串}//******************************************************************************************【4】对给定数组进行操作,模拟多媒体解码JNIEXPORT jintArray JNICALL Java_com_bqt_hellofromc_MyNativeMethods_intMethod(JNIEnv * env, jobject jobject, jintArray arr) {int len = (*env)->GetArrayLength(env, arr); // 获取数组的长度LOGI("ArrayLength=%d", len);//LOG中也不能有中文jint* p = (*env)->GetIntArrayElements(env, arr, 0); //取出数组中第一个元素的内存地址//If isCopy is not NULL, then *isCopy is set to JNI_TRUE if a copy ismade; if no copy is made, it is set to JNI_FALSE.int i = 0;for (; i < len; i++) {LOGI("before-%d-=%d", i, *(p+i));//这一步没问题,会一个个打印所有数组中的内容*(p + i) += 5; //取出的每个元素加5LOGI("after-%d-=%d", i, *(p+i));//这一步也没问题,会一个个打印处理后的内容}jint* elems = (*env)->GetIntArrayElements(env, arr, 0); //再次获取元素的内存地址LOGI("ok-%d-=%d", i, *elems);//但返回的为啥还是未经处理的?//重新创建一个数组jintArray array = (*env)->NewIntArray(env, len); //Construct构造 a new primitive array object基本数组对象int ii = 0;int jj;for (; ii < len; ii++) {jj = 10000 + ii;(*env)->SetIntArrayRegion(env, array, ii, 1, &jj); //Sets the value of one element in a primitive array.其中【&】代表【取地址】操作,而非逻辑操作//(*env)->SetIntArrayRegion(env,array,【start】,【len】,buffer) , 从start开始复制长度为len 的数据 buffer到 array 中}return array;}//******************************************************************************************【工具方法】把java的字符串转换成c的字符串char* Jstring2CStr(JNIEnv* env, jstring jstr) {char* rtn = NULL;//1:先找到字节码文件jclass clsstring = (*env)->FindClass(env, "Java/lang/String"); //Java或java都一样jstring strencode = (*env)->NewStringUTF(env, "GB2312"); //和UTF-8不行//2:通过字节码文件找到方法IDjmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");//3:通过方法id,调用方法jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");//4:得到数据的长度jsize alen = (*env)->GetArrayLength(env, barr);//5:得到数据的首地址jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);//6:得到C语言的字符串if (alen > 0) {rtn = (char*) malloc(alen + 1); //"\0"memcpy(rtn, ba, alen);rtn[alen] = 0;}(*env)->ReleaseByteArrayElements(env, barr, ba, 0); //return rtn;}
c++文件
#include <stdio.h>#include <stdlib.h>#include <jni.h>#include "com_bqt_hellofromc_MyNativeMethods.h"//引入生成的头文件,这个东西在这里又必须要了!JNIEXPORT jstring JNICALL Java_com_bqt_hellofromc_MyNativeMethods_helloFromCPP(JNIEnv *env, jobject obj) {return env->NewStringUTF("hello c++");}
Android.mk文件
LOCAL_PATH := $(call my-dir)# C/C++代码所在目录,也就是我们的jni目录,不必修改include $(CLEAR_VARS)LOCAL_LDLIBS += -llog#若要在C中使用log,①需在.c中添加一系列声明,②还需在Android.mk文件中增加【LOCAL_LDLIBS += -llog】#必须把LOCAL_LDLIBS :=-llog放在【include $(CLEAR_VARS)】后面才有用LOCAL_MODULE := hello# 对应打包成函数库的名字,编译器会自动在前面加上lib,在后面加上.soLOCAL_SRC_FILES := hello.c# 对应c代码的文件 hello.c#不知道能不能同时编译多个#LOCAL_MODULE := hellocpp#LOCAL_SRC_FILES := hello.cppinclude $(BUILD_SHARED_LIBRARY)
Application.mk文件
APP_ABI := armeabi armeabi-v7a x86#Application.mk文件的目的是,描述在你的应用程序中所需要的模块(即静态库或动态库)#APP_ABI 的值以空格区分,代表要支持的架构,默认为【armeabi】。其他架构,ARMv7 【armeabi-v7a】;IA-32 【 x86】#每增加一个架构,编译后都会在lib目录下生成一个相应的文件夹,文件夹下的文件都是同名的.so文件(当然文件内容不一样)
javah生成的.h头文件
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_bqt_hellofromc_MyNativeMethods */#ifndef _Included_com_bqt_hellofromc_MyNativeMethods#define _Included_com_bqt_hellofromc_MyNativeMethods#ifdef __cplusplusextern "C" {#endif/** Class: com_bqt_hellofromc_MyNativeMethods* Method: helloFromC* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_bqt_hellofromc_MyNativeMethods_helloFromC(JNIEnv *, jobject);/** Class: com_bqt_hellofromc_MyNativeMethods* Method: passwordFromC* Signature: (II)I*/JNIEXPORT jint JNICALL Java_com_bqt_hellofromc_MyNativeMethods_passwordFromC(JNIEnv *, jobject, jint, jint);/** Class: com_bqt_hellofromc_MyNativeMethods* Method: encodeFromC* Signature: (Ljava/lang/String;I)Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_bqt_hellofromc_MyNativeMethods_encodeFromC(JNIEnv *, jobject, jstring, jint);/** Class: com_bqt_hellofromc_MyNativeMethods* Method: intMethod* Signature: ([I)[I*/JNIEXPORT jintArray JNICALL Java_com_bqt_hellofromc_MyNativeMethods_intMethod(JNIEnv *, jobject, jintArray);/** Class: com_bqt_hellofromc_MyNativeMethods* Method: helloFromCPP* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_bqt_hellofromc_MyNativeMethods_helloFromCPP(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
附件列表
JNI Java调用C代码 示例的更多相关文章
- 通过JNI实现java调用C代码和C代码调用java的代码
一.java调用C代码 1)java中需要声明调用的函数,也就是native方法,并通过System.LoadLibrary来调用dll或者so(C代码).实例代码如下: public class H ...
- windows和linux环境下java调用C++代码-JNI技术
最近部门做安卓移动开发的需要调C++的代码,困难重重,最后任务交给了我,查找相关资料,没有一个教程能把不同环境(windows,linux)下怎么调用说明白的,自己在实现的过程中踩了几个坑,在这里总结 ...
- java调用python代码
同样的我们需要安装jython,具体的步骤如下: 1. 去 http://sourceforge.net/projects/jython/ 下载最新的jython相关的jar包. 2. 下载下来的ja ...
- cocos2d 中使用jni Java 调用 C++ 方法
1.首先是LoadLibrary cocos2d中的C++代码会编译成一个.so文件.放在安卓文件夹下的libs/armeabi 下,然后java会load进来,这步我们不用做了,由于cocos2d已 ...
- C++用LuaIntf调用Lua代码示例
C++用LuaIntf调用Lua代码示例 (金庆的专栏 2016.12) void LuaTest::OnResponse(uint32_t uLuaRpcId, const std::string& ...
- 01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用
1 什么是JNI JNI Java本地开发接口 JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(C/C++) 通过这个协议,java代码就可以调用外部的C/C++代码,外部的C/C++ ...
- [JNI] Java 调用 C++ dll
首先介绍一下JNI吧! JNI 是Java提供的一个用于调用本地接口的接口层,位于Java代码 和 本地代码之间的一层:主要功能是 数据类型的转换,还有就是通过这一层来调用本地代码! 下面就说说Jav ...
- 天气类API调用的代码示例合集:全国天气预报、实时空气质量数据查询、PM2.5空气质量指数等
以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 全国天气预报:数据来自国家气象局,可根据地名.经纬度GPS.IP查 ...
- 位置信息类API调用的代码示例合集:中国省市区查询、经纬度地址转换、POI检索等
以下示例代码适用于 www.apishop.net 网站下的API,使用本文提及的接口调用代码示例前,您需要先申请相应的API服务. 中国省市区查询:2017最新中国省市区地址 经纬度地址转换:经纬度 ...
随机推荐
- K-means聚类
聚类算法,无监督学习的范畴,没有明确的类别信息. 给定n个训练样本{x1,x2,x3,...,xn} kmeans算法过程描述如下所示: 1.创建k个点作为起始质心点,c1,c2,...,ck 2.重 ...
- log4net编译后命名空间找不到的问题
log4net编译后命名空间找不到的问题问题:工程A添加dll引用后,可以在代码中引入log4net的命名空间.工程B引用A.A能编译成功,B不能编译成功,提示找不到命名空间. 解决: 点击项目属性- ...
- js删除选中的复选框中的父辈。
function scsx(){ var cb=document.getElementsByName('checkbox') if(confirm('删除?')){ for (var i=0;i< ...
- HTml <meta>标签的使用(重要)
<meta> 元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词. 1.设置网页字符编码 <meta http-equiv=&q ...
- 利用WebApi获取手机号码归属地
前述: 在WebApi中,涉及到一个重要的类,HttpWebRequest. 学习link:httpwebrequest详解 示例演示: 代码示例: 1.前端代码: @{ ViewBag.Title ...
- ASP.NET MVC 实现与SQLSERVER的依赖缓存
原文:ASP.NET MVC 实现与SQLSERVER的依赖缓存 本文主要是为了了解ASP.NET MVC 实现与SQLSERVER的依赖缓存的功能,针对自己对于这方面知识的学习的过程的一个记录.由于 ...
- Subway POJ 2502
题目链接: http://poj.org/problem?id=2502 题目大意: 你刚从一个安静的小镇搬到一个吵闹的大城市,所以你不能再骑自行车去上学了,只能乘坐地铁或者步行去上学.因为你不想迟到 ...
- HDOJ 1020 Encoding
Problem Description Given a string containing only 'A' - 'Z', we could encode it using the following ...
- Maven搭建环境(Linux& Windows)
Linux下安装Maven 1.前提条件: 1)下载并安装好JDK .在终端输入命令“java -version”,如果出现类似如下信息说明JDK安装成功. $ java -version java ...
- Alert Views
Alert views display a concise and informative alert message to the user. Alert views convey importan ...