Android NDK Development (iv)--java passing data to C

Source: Internet
Author: User

Reprint Please specify source:http://blog.csdn.net/allen315410/article/details/41845701

A few previous articles introduced the simple concept of Android NDK development, common mistakes and handling and starting with the first Hello world to actually do a simple JNI development example, I believe after reading, we have a conceptual understanding of the NDK development, So next we need to go deeper into the NDK development, and we know that the NDK development is using the JNI layer "protocol" to play a "bridge" between Java and C, linking Java and native C to make the Java and C direct data intermodulation. When it comes to data calls between Java and C, how does Java pass data to C, and C to get the processed data back to Java after it has been processed? Don't worry, let's see how Java passes the data to C.

1, build an Android project, create a Dataprovider class under engineering, and define 3 native methods in this class, as follows:

Package Com.example.ndktransferdata;public class Dataprovider {/** * transfers int from two Java to the C language, and when the C language is finished, the added result is returned to Java *  * @param x * @param y * @return */public native int Add (int x, int y);/** * Pass a string in Java to the C language, and after the C language gets, add a hello word after the string String, return to Java *  * @param s * @return */public Native string Sayhelloinc (string s);/** * pass an int array in Java to the C language, C to receive this array, put I Each element in the NT array is +10 and then returned to Java *  * @param iNum * @return */public native int[] Intmethod (int[] iNum);}
2, compile the header file with Javah

Do this step found a problem, from the description should be a coding error, where the wrong use of GBK to compile Java files, change to UTF-8 is no problem, as long as the Javah command to add-encoding utf-8, for the compiler to provide the encoding environment on the line, Here are the results after correction:


Note that the function signature of the native code has been generated, we cut the generated function signature header file into the JNI directory, and reference the file in C code.

/* Don't EDIT this file-it are machine generated */#include <jni.h>/* Header for class Com_example_ndktransferdata _dataprovider */#ifndef _included_com_example_ndktransferdata_dataprovider#define _included_com_example_ Ndktransferdata_dataprovider#ifdef __cplusplusextern "C" {#endif/* * Class:com_example_ndktransferdata_dataprovider  * Method:add * Signature: (II) I */jniexport jint jnicall java_com_example_ndktransferdata_dataprovider_add (JNIENV *, Jobject, Jint, jint);/* * Class:com_example_ndktransferdata_dataprovider * method:sayhelloinc * Signature: (ljav a/lang/string;) ljava/lang/string; */jniexport jstring jnicall java_com_example_ndktransferdata_dataprovider_sayhelloinc (JNIENV *, Jobject, jstring);/* * Class:com_example_ndktransferdata_dataprovider * Method:intmethod * Signature: ([i) [I */jniexport Jintarray JNI Call Java_com_example_ndktransferdata_dataprovider_intmethod (JNIEnv *, Jobject, jintarray); #ifdef __cplusplus}# Endif#endif

3, write the C language code

Before the second step we compiled the function signature of the header file, so here we need to use the method in the file to sign, a total of 3 such native functions, the implementation of the function is this:

#include <stdio.h> #include <jni.h> #include <malloc.h> #include <string.h> #include "com_ Example_ndktransferdata_dataprovider.h "#include <android/log.h> #define LOG_TAG" system.out.c "#define LOGD ( ...) __android_log_print (Android_log_debug, Log_tag, __va_args__) #define Logi (...) __android_log_print (ANDROID_LOG_INFO , Log_tag, __va_args__)/** * Return value char* This represents the first address of the char array * JSTRING2CSTR converts the type of jstring in Java into a char string in the C language */char* Jstring2 CSTR (jnienv* env, jstring jstr) {char* Rtn = Null;jclass clsstring = (*env)->findclass (env, "java/lang/string");//Stri Ngjstring Strencode = (*env)->newstringutf (env, "GB2312"); Get a Java string "GB2312" jmethodid mid = (*env)->getmethodid (env, clsstring, "GetBytes", "(ljava/lang/string;) [B");// [String.getbytes ("gb2312"); Jbytearray Barr = (Jbytearray) (*env)->callobjectmethod (env, JSTR, mid,strencode);// String. GetByte ("GB2312"); Jsize alen = (*env)->getarraylength (env, Barr); The length of the byte array jbyte* ba = (*env)->getbytearrayeLements (env, Barr, Jni_false); if (Alen > 0) {rtn = (char*) malloc (alen + 1);//"memcpy" (RTN, BA, Alen); Rtn[alen] = 0; } (*ENV)->releasebytearrayelements (env, Barr, BA, 0); return RTN;} Jniexport jint jnicall java_com_example_ndktransferdata_dataprovider_add (jnienv * env, Jobject obj, Jint x, Jint y) {LOGD ( "x =%d", x); Logd ("y =%d", y); return x + y;} Jniexport jstring jnicall java_com_example_ndktransferdata_dataprovider_sayhelloinc (JNIENV * env, jobject obj, jstring JSTR) {char* CStr = jstring2cstr (env, JSTR); LOGD ("CStr =%s", CStr), char arr[7] = {', ' h ', ' e ', ' l ', ' l ', ' o ', '};strcat ' (CStr, arr); LOGD ("New CStr =%s", CStr), return (*ENV)->newstringutf (env, CSTR);} Jniexport jintarray jnicall Java_com_example_ndktransferdata_dataprovider_intmethod (JNIENV * env, Jobject obj, Jintarray Jarr) {//Gets the length of the passed in array int len = (*env)->getarraylength (env, Jarr);//Gets the element passed in the array, that is, the first address of the array jint* intarr = (*env)- >getintarrayelements (env, Jarr, 0); int i = 0;for (; i < Len; i++) {//number before printing processingGroup element Logd ("intarr[%d] =%d", I, intarr[i]);//traversal array element +10* (Intarr + i) + = 10;} return Jarr;}

4. Configure the Android.mk file

    Local_path: = $ (call My-dir)    include $ (clear_vars)    local_module    : = Hello    local_src_files: = hello.c        Local_ldlibs + =-llog    include $ (build_shared_library)
Light Configuration The Android.mk file is generally available, but a version compatibility issue needs to be resolved by creating a new Application.mk file in the JNI directory, plus

App_platform: = android-8

5, compiling C language code

Processing the returned data in 6,java code

Java in the transfer of data to C code, c code after processing to return to Java, when Java to get the data can do their own business operations, first we compile native code, first refresh the project, and then clean the project, write the following test cases:

public class Mainactivity extends Activity implements Onclicklistener {//load local library file static {system.loadlibrary ("Hello");} Private Button btn1, BTN2, btn3;private dataprovider provider; @Overrideprotected void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); btn1 = (Button) Findviewbyid (R.ID.BTN1); btn2 = (Button) Findviewbyid (R.ID.BTN2); btn3 = (Button) Findviewbyid (R.ID.BTN3); Btn1.setonclicklistener (This), Btn2.setonclicklistener (This), Btn3.setonclicklistener (this);p Rovider = new Dataprovider ();} @Overridepublic void OnClick (View v) {switch (V.getid ()) {case R.ID.BTN1://pass 2 int to c code int result = Provider.add (3, 5); T Oast.maketext (This, "added result:" + result, 0). Show (); Break;case r.id.btn2://Pass string to c code string str = Provider.sayhelloinc ( "Zhang San"); Toast.maketext (this, str, 0). Show (); Break;case r.id.btn3://Pass int array to C code int[] arr = {1, 2, 3, 4, 5};p Rovider.intmethod (AR R); for (int i = 0; i < arr.length; i++) {System.out.println ("arr["+ i +"] = "+ Arr[i]);} Break;default:break;}}}
Run the project, note: This can only open the ARM emulator, if the x86 simulator will install the APK when the error, because this section of the native code only written arm supported version, no support x86. If there are some errors when running the test, please refer to the previous article for a prompt resolution.Android NDK Development--common error collection and log usage

Test 1:java pass 2 int to C


Logcat output:


Test 2:java Pass string to C


Logcat output:


test 3:java Pass int array to c

Logcat output:


Summary:

This simple example illustrates how Java is passing data to C code in the NDK development, which simply introduces 3 data types Int,string and int[], which is far from enough because Java supports more data types than it does. Well, with the above example, we can extrapolate, in the previous blog I also emphasized the NDK decompression package jni.h The importance of this file, this file not only defines the Java data type in the C language of the expression, look at the source code, we found a mapping relationship:

... typedef uint8_t Jboolean;          /* Unsigned 8 bits */typedef int8_t jbyte;          /* Signed 8 bits */typedef uint16_t Jchar;         /* unsigned-bits */typedef int16_t jshort;           /* Signed-bits */typedef int32_t jint;          /* Signed-bits */typedef int64_t jlong;         /* Signed-bits */typedef float jfloat;        /* 32-bit IEEE 754 */typedef double jdouble;       /* 64-bit IEEE 754 */#elsetypedef unsigned char jboolean;          /* Unsigned 8 bits */typedef signed char jbyte;          /* Signed 8 bits */typedef unsigned short jchar;         /* unsigned bits */typedef short jshort;           /* Signed-bits */typedef int jint;          /* Signed */typedef long long Jlong;         /* Signed-bits */typedef float jfloat;        /* 32-bit IEEE 754 */typedef double jdouble; /* 64-bit IEEE 754 */...
There is also a very important structural body jninativeinterface, which defines a lot of C functions, as long as the general meaning can be tried to call these functions, these functions in the development of native is particularly important:

... Jbooleanarray (*newbooleanarray) (jnienv*, jsize);    Jbytearray (*newbytearray) (jnienv*, jsize);    Jchararray (*newchararray) (jnienv*, jsize);    Jshortarray (*newshortarray) (jnienv*, jsize);    Jintarray (*newintarray) (jnienv*, jsize);    Jlongarray (*newlongarray) (jnienv*, jsize);    Jfloatarray (*newfloatarray) (jnienv*, jsize);    Jdoublearray (*newdoublearray) (jnienv*, jsize);    jboolean* (*getbooleanarrayelements) (jnienv*, Jbooleanarray, jboolean*);    Jbyte* (*getbytearrayelements) (jnienv*, Jbytearray, jboolean*);    Jchar* (*getchararrayelements) (jnienv*, Jchararray, jboolean*);    jshort* (*getshortarrayelements) (jnienv*, Jshortarray, jboolean*);    jint* (*getintarrayelements) (jnienv*, Jintarray, jboolean*);    jlong* (*getlongarrayelements) (jnienv*, Jlongarray, jboolean*);    jfloat* (*getfloatarrayelements) (jnienv*, Jfloatarray, jboolean*); Jdouble* (*getdoublearrayelements) (jnienv*, Jdoublearray, jboolean*);...... 
The source is relatively long, interested friends to look over, here only part.


Please download the source code here


Android NDK Development (iv)--java passing data to C

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.