[jni] 02_jni中C和C++的区别

Android 4.0

JNI中C和C++的区别

jni.h,从500行开始,是C++对C的包装
struct _JNIEnv {
    /* do not rename this; it does not seem to be entirely opaque */
    const struct JNINativeInterface* functions;
    jclass FindClass(const char* name)
    { return functions->FindClass(this, name); }
}
C++和C在使用jni上的区别:
1、在Android.mk中C++需要扩展库
LOCAL_CPP_EXTENSION := cpp  
2、调用方法时,前面不要写(*env)。直接写env。内部给封装了
3、方法中的参数不要写env了
env->NewStringUTF(ch1);  
4、生成的方法签名,不要用的参数,可以不用写
JNIEXPORT jstring JNICALL Java_cn_zengfansheng_jniccplusplus_MainActivity_helloInCplusplus(
        JNIEnv *env, jobject, jstring jstr) {}
核心代码:
1、Hello.cpp
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <jni.h>
#include <android/log.h>
#include "cn_zengfansheng_jniccplusplus_MainActivity.h"
#define LOG_TAG "System.out.c" //在LogCat上打印出来的Tag
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

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

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

    char* ch = Jstring2CStr(env,jstr);
    LOGD("%s", ch);
//    jstring NewStringUTF(const char* bytes)
//        { return functions->NewStringUTF(this, bytes); }
    char* ch1 = "i am from c";
    return env->NewStringUTF(ch1);
    //1、调用不需要(*env)->,
    //2、参数中不需要env
}
2、Android.mk
LOCAL_PATH :$(call my-dir)
include $(CLEAR_VARS)

#    Since NDK r7, you can list several extensions in this variable, as in:
#    LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_CPP_EXTENSION := cpp

LOCAL_MODULE    := MyHello
LOCAL_SRC_FILES := Hello.cpp

#     LOCAL_LDLIBS := -lz
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)