一步一步学习androidNDK编程(java给c传递数据)

这篇已经是"一步一步学习androidNDK编程"的第四篇了,在这篇中,我们将会在java中传递代码给c代码。

首先,我们新建一个android工程"ndkdata",

第一步:

同样的首先声明native方法,如下:

public native int add(int a,int b);
public native String helloSir(String name);
public native int[] intMethod(int[] intArray);

可以看到我这里声明了三个方法,用来传递不同的数据类型给c代码

第二步:

由于我们的这些方法都是声明在MainActivity.java中的,所以我们需要首先将该MainActivity.java用javac编译为.class文件,然后运用javah,生成对应的.h头文件。

将该MainActivity.java用javac编译为.class文件:这个就是运行该android工程即可在bin/classes目录下生成对应的.class文件。

命令行下进入bin/classes所在的目录:执行javah com.example.ndkdata.MainActivity即可在该目录下生成对应的com_example_ndkdata_MainActivity.h头文件了,内容如下:

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

#ifndef _Included_com_example_ndkdata_MainActivity
#define _Included_com_example_ndkdata_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_ndkdata_MainActivity
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_example_ndkdata_MainActivity
 * Method:    helloSir
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_example_ndkdata_MainActivity
 * Method:    intMethod
 * Signature: ([I)[I
 */
JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod
  (JNIEnv *, jobject, jintArray);

#ifdef __cplusplus
}
#endif
#endif

接下来我们在ndkdata工程中,创建jni目录,然后再将刚才生成的com_example_ndkdata_MainActivity.h文件拷贝到该目录下,然后创建我们的c代码:hello.c

将com_example_ndkdata_MainActivity.h中生成的方法添加到hello.c文件中这里需要添加参数,因为默认生成的只有方法的参数类型,没有参数对象,并且引入对应的头文件,如下:

#include<stdio.h>
#include<jni.h>
#include "com_example_ndkdata_MainActivity.h"

JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add
  (JNIEnv * env, jobject obj, jint x, jint y) {

}

JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir
  (JNIEnv * env, jobject obj, jstring jstr) {

}

JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod
  (JNIEnv * env, jobject obj, jintArray arr) {

}

接下来就是实现我们的c代码了,如下:

#include<stdio.h>
#include<jni.h>
#include "com_example_ndkdata_MainActivity.h"

JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add
  (JNIEnv * env, jobject obj, jint x, jint y) {
  
  return x+y;
  
}

/**
 * 返回值 char* 这个代表char数组的首地址
 *  Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
 */
char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)
{
<span style="white-space:pre">	</span> char*   rtn   =   NULL;
<span style="white-space:pre">	</span> jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String"); //String
<span style="white-space:pre">	</span> jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");  // 得到一个java字符串 "GB2312"
<span style="white-space:pre">	</span> jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
<span style="white-space:pre">	</span> jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
<span style="white-space:pre">	</span> jsize   alen   =   (*env)->GetArrayLength(env,barr); // byte数组的长度
<span style="white-space:pre">	</span> jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
<span style="white-space:pre">	</span> if(alen   >   0)
<span style="white-space:pre">	</span> {
<span style="white-space:pre">	</span>  rtn   =   (char*)malloc(alen+1);         //"\0"
<span style="white-space:pre">	</span>  memcpy(rtn,ba,alen);
<span style="white-space:pre">	</span>  rtn[alen]=0;
<span style="white-space:pre">	</span> }
<span style="white-space:pre">	</span> (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //
<span style="white-space:pre">	</span> return rtn;
}

JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir
  (JNIEnv * env, jobject obj, jstring jstr) {
  
  //在c语言中 是没有java的String
<span style="white-space:pre">	</span>char* cstr = Jstring2CStr(env, jstr);
<span style="white-space:pre">	</span>// c语言中的字符串 都是以'\0' 作为结尾
<span style="white-space:pre">	</span>char arr[7]= {' ','h','e','l','l','o','\0'};
<span style="white-space:pre">	</span>strcat(cstr,arr);
<span style="white-space:pre">	</span>return (*env)->NewStringUTF(env,cstr);
  
  
}

JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod
  (JNIEnv * env, jobject obj, jintArray arr) {
    
}

编写完了hello.c之后,需要编写Android.mk,内容如下:

#交叉编译编译c/c++代码所依赖的配置文件

#获取当前Android.mk的路径
LOCAL_PATH := $(call my-dir)

#变量初始化操作
include $(CLEAR_VARS)

#libhello.so 其实生成的libhello.so就是在我们这个模块的名称前面加上lib后边加上.so
LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c

include $(BUILD_SHARED_LIBRARY)

现在就需要在cygwine的命令行下进入该工程ndkdata的根目录下,执行"ndk-build"命令生成对应的可直接运行的二进制文件,注意每次在执行"ndk-build"之后最好将android工程clean一下。

在“ndk-build”成功之后,需要在java代码中引入这些库文件:

static {
        System.loadLibrary("hello");
}

注意这里的"hello",就是我们在Android.mk文件中写的模块名,即LOCAL_MODULE的值。

现在,就可以执行声明的native方法了,在java代码中直接调用即可,是不是很简单呢。

源码下载

时间: 2024-10-01 05:45:50

一步一步学习androidNDK编程(java给c传递数据)的相关文章

MVC学习系列9--从视图向控制器传递数据

前面学习了,从控制器向视图传递数据,现在学习怎么从视图向控制器传递数据. 通常,我们有两种方式,来处理浏览器的请求,一个是GET方式,一个是POST方式.一般来说,直接通过在浏览器中输入URL话,请求的方式是GET,那么GET方式的Action方法将会被调用,另一方面,如果是点击一个Button提交一个表单的话,这个时候POST方式的Action就会被调用. 这里我们说的是POST方式,怎么从视图向控制器传递数据,即把用户输入的表单信息的数据,传递到控制器对应的Action方法中. 这里先列举一

一步一步学习androidNDK编程(log调试和解决中文乱码)

上一篇说到了androidNDK编程的helloworld,今天,学习了如何在ndk开发时候,在c代码当中,向java代码那样,打印出log 1. 我们需要引入头文件: #include <android/log.h> 2.定义打印的tag,这里相当于java中的static final类型 #define LOG_TAG "onEvent" 3.定义宏,相当于声明一个方法: #define LOGD(fmt, args...) __android_log_print(AN

一步一步学习androidNDK编程(hello world)

上一篇博客,已经搭建好了windows下的linux环境(cygwine),这次我们试着写一个hello world.首先需要去android的官网下载android-ndk压缩包,之后解压,进入解压后的目录,我们发现有一个ndk-build的脚本文件,这个脚本文件就是我们用交叉编译的文件.我们通过  "./ndk-build"  来运行该命令,如下图: 因为目前我们没有编译任何c代码,所以会提示"could not find application project dire

Java多线程学习笔记——从Java JVM对多线程数据同步的一些理解

   我们知道在多线程编程中,我们很大的一部分内容是为了解决线程间的资源同步问题和线程间共同协作解决问题.线程间的同步,通俗我们理解为僧多粥少,在粥有限情况下,我们怎么去防止大家有秩序的喝到粥,不至于哄抢都没得喝.线程讲协作,我们可以理解为我们在医院看病的时候,我们要先挂号,才能看病.现在医院有很多病人排队,怎么协调病人都有秩序的先挂号,后看病.本篇文章的重点不在此,也不是在此一下子能分析完,我们先从Java JVM的角度来理解多线程的一些方面. 我们知道多线程间的数据同步,我们是通过加锁的操作

【JVM学习】2.Java虚拟机运行时数据区

来源: 公众号: 猿人谷 这里我们先说句题外话,相信大家在面试中经常被问到介绍Java内存模型,我在面试别人时也会经常问这个问题.但是,往往都会令我比较尴尬,我还话音未落,面试者就会"背诵"一段(Java虚拟机是由堆.方法区.虚拟机栈,吧啦吧啦...),估计心里还一脸自豪的想幸好哥提前在网上搜过,早有准备.每每这个时候,我都不忍心打断,因为"背诵"的真的太顺畅了! 这也怪不得面试者,首先Java虚拟机方面的知识,对中高级程序猿来说,工作中正面接触Java虚拟机的东西

Android第一行代码学习笔记六---Intent向活动传递数据

@1.向下一个活动传递数据: Intent提供了一系列putExtra()方法的重载,可以把我们想要传递的数据暂存在Intent中,启动了另一个活动后,只需把这些数据再从Intent中取出就可以了,比如firstActivity中有一个字符串要传递到secondActivity中,修改firstActivity中按钮点击事件,代码可以这样编写: button.setOnClickListener(new View.OnClickListener() { public void onClick(V

Andoid Intent学习之在各个活动之间传递数据

Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程中连接两个不同的组件.通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来完成请求. 1.使用Intent向下一个活动传递数据 在activity_main.xml中添加一个Button <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

机器码农:深度学习自动编程

转自原文机器码农:深度学习自动编程 作者简介:张俊林,中科院软件所博士,曾担任阿里巴巴.百度.新浪微博资深技术专家,目前是用友畅捷通工智能相关业务负责人,关注深度学习在自然语言处理方面的应用. 责编:何永灿,欢迎人工智能领域技术投稿.约稿.给文章纠错,请发送邮件至[email protected] 本文为<程序员>原创文章,未经允许不得转载,更多精彩文章请订阅2017年<程序员> 机器自动编程是人工智能一直以来期望攻克的重要应用领域,随着深度学习的逐步流行,最近在自动编程方向获得了

Android NDK 开发(四)java传递数据到C【转】

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处理和从第一个Hello World开始实际做一个简单的JNI开发示例,相信看完之后,大家对NDK开发有了一个概念上的认识了,那么接下来我们需要再深入一下NDK的开发,我们知道NDK开发就是使用JNI这层“协议”在Java和C之间起个“桥梁”的作用,将Java和Native C之间联立起来,让Java