C++11 JNI开发中RAII的应用(二)--JNI函数封装

来源:互联网 发布:nginx http referer 编辑:程序博客网 时间:2024/06/14 19:44

在上一节《C++11 JNI开发中RAII的应用(一)》中我们已经有了一些基本的RAII封装工具,本节就简单了,就是根据需要把一些常用的JNIEnv函数封装成更方便使用的模板函数。

raii_NewGlobalRef

raii_NewGlobalRef函数顾名思义,就是封装JNIEnv::NewGlobalRef,将一个本地引用的jobject转为全局引用封装在raii_var中。

    /* 封装JNIEnv::NewGlobalRef 返回jobject对象全局引用(RAII管理) */    template<typename T=jobject,typename TYPE=typename std::conditional<!std::is_same<T,jobject>::value,T,jobject>::type>    static raii_var<TYPE>    raii_NewGlobalRef(T localRef) {        static_assert(                std::is_base_of<typename std::remove_pointer<jobject>::type,                                        typename std::remove_pointer<T>::type>::value,                "T is not derived from jobject");        return raii_var<TYPE>(            [localRef]()->TYPE {return static_cast<TYPE>(getJNIEnv()->NewGlobalRef(localRef));},            [](TYPE &gref) {getJNIEnv()->DeleteGlobalRef(gref);});    }

在调用时,如果不指定T的类型,则返回的raii_var类中的类型默认为jobject,否则

下面所有的模板函数都是这个用法。

raii_FindClass_LocalRef & raii_FindClass_GlobalRef

raii_FindClass_LocalRefraii_FindClass_GlobalRef,封装了JNIEnv::FindClass,返回字符串name指定的类名的jclass对象,raii_FindClass_LocalRef 返回的是本地引用,raii_FindClass_GlobalRef返回全局引用。

    /* 封装JNIEnv::FindClass 返回jclass对象局部引用(RAII管理) */        static raii_var<jclass> raii_FindClass_LocalRef(const char* name) {        assert(nullptr != name);        return raii_jobject_env(&JNIEnv::FindClass, name);    }    /* 封装JNIEnv::FindClass 返回jclass对象全局引用(RAII管理) */    static raii_var<jclass> raii_FindClass_GlobalRef(const char* name) {        return raii_NewGlobalRef<jclass>(raii_FindClass_LocalRef(name).get());    }

比如:

auto jstring_class=raii_FindClass_LocalRef("Ljava/lang/String;");//返回String类的jclass对象

raii_GetObjectClass

raii_GetObjectClass封装JNIEnv::GetObjectClass,返回一个jobjectjclass对象

    static raii_var<jclass> raii_GetObjectClass(jobject obj) {        assert(nullptr != obj);        return raii_jobject_env(&JNIEnv::GetObjectClass, obj);    }

raii_CallObjectMethod

raii_CallObjectMethod封装JNIEnv:CallObjectMethod

//通过methodID调用指定的方法    template<typename T=jobject,typename... Args>    static raii_var<T> raii_CallObjectMethod( jobject obj, jmethodID methodID, Args&&... args) {        return raii_jobject_env<T>(&JNIEnv::CallObjectMethod,obj, methodID,std::forward<Args>(args)...);    }//通过name指定的方法名和sig指定的方法签名调用指定的方法    template<typename T=jobject,typename... Args>    static raii_var<T> raii_CallObjectMethod( jobject obj, const char *name, const char *sig, Args&&... args) {        raii_var<jclass> clazz=raii_GetObjectClass(obj);        auto methodID = getJNIEnv()->GetMethodID(clazz.get(), name, sig);        assert(nullptr != methodID);        return raii_CallObjectMethod<T>(obj,methodID,std::forward<Args>(args)...);    }

raii_NewObject

raii_NewObject封装JNIEnv::NewObject有5个重载函数

//通过constructor指定的jmethodID调用指定的构造方法    template<typename T=jobject,typename... Args>    static raii_var<T> raii_NewObject( jclass clazz, jmethodID constructor, Args&&... args) {        return raii_jobject_env(&JNIEnv::NewObject,clazz,constructor,std::forward<Args>(args)...);    }//通过sig指定的构造方法签名来调用指定的构造方法    template<typename T=jobject,typename... Args>    static raii_var<T> raii_NewObject( jclass clazz, const char *sig, Args&&... args) {        assert(nullptr != clazz);        auto constructor = getJNIEnv()->GetMethodID(clazz, "<init>", nullptr==sig?"void (V)":sig);        assert(nullptr != constructor);        return raii_NewObject<T>(clazz,constructor,std::forward<Args>(args)...);    }//通过class_name指定类名和sig指定的构造方法签名来创建新对象       template<typename T=jobject,typename... Args>    static raii_var<T> raii_NewObject( const char * class_name, const char *sig,Args&&... args) {        return raii_NewObject<T>(raii_FindClass_LocalRef(class_name).get(),sig,std::forward<Args>(args)...);    }//用默认构造方法创建clazz指定的对象    template<typename T=jobject>    static raii_var<T> raii_NewObject( jclass clazz) {        return raii_NewObject<T>(clazz,(const char *)nullptr);    }//用默认构造方法创建clas_name指定的对象    template<typename T=jobject>    static raii_var<T> raii_NewObject( const char * class_name) {        return raii_NewObject<T>(raii_FindClass_LocalRef(class_name).get());    }

raii_NewByteArray

raii_NewByteArray封装JNIEnv::NewByteArray,创建指定长度的byte数组

    static raii_var<jbyteArray> raii_NewByteArray( jsize len) {        return raii_jobject_env(&JNIEnv::NewByteArray, len);    }

tojbytearray

调用raii_NewByteArray将一个C++的字节数组转为java字节数组(jbyteArray)

    /* 将bytes转成raii_var<jbyteArray>对象 */    static raii_var<jbyteArray> tojbytearray(jbyte* bytes, jsize len) {        auto byteArray = raii_NewByteArray(len);        if (nullptr != bytes)            getJNIEnv()->SetByteArrayRegion(byteArray.get(), 0, len, bytes);        return byteArray;    }

raii_NewStringUTF&raii_NewString

raii_NewStringUTF封装JNIEnv::NewStringUTF,将一个UTF-8编码的字符串转为java String(jstring)
raii_NewStringUTF封装JNIEnv::NewString,将一个Unicode 编码的jchar数组转为java String(jstring)

    /* 将UTF-8字符串转成一个raii_var管理的JString对象 */    static raii_var<jstring> raii_NewStringUTF(const char* pStr) {        return raii_jobject_env(&JNIEnv::NewStringUTF, pStr);    }    /* 将Unicode字符串转成一个raii_var管理的JString对象 */    static raii_var<jstring> raii_NewString(const jchar* pStr, jsize len) {        return raii_jobject_env(&JNIEnv::NewString, pStr, len);    }

raii_GetObjectField

raii_GetObjectField封装JNIEnv::GetObjectField,返回指定fieldID的对象(jobject)

    /* 封装JNIEnv::GetObjectField 返回T指定的jobject基类对象(RAII管理) */    template<typename T=jobject>    static raii_var<T> raii_GetObjectField(jobject obj, jfieldID fieldID) {        return raii_jobject_env<T>(&JNIEnv::GetObjectField,obj,fieldID);    }

raii_GetObjectArrayElement

raii_GetObjectArrayElement封装JNIEnv::GetObjectArrayElement,返回对象数组指定下标的java 对象(jobject)

    /* 封装JNIEnv::GetObjectField 返回T指定的jobject基类对象(RAII管理) */    template<typename T=jobject>    static raii_var<T> raii_GetObjectArrayElement(jobjectArray array, jsize index) {        return raii_jobject_env<T>(&JNIEnv::GetObjectArrayElement,array,index);    }

raii_GetByteArrayElements

raii_GetByteArrayElements封装JNIEnv::GetByteArrayElements,返回java字节数组byte[]的C++字节数组

    static auto raii_GetByteArrayElements(jbyteArray bytes, jint release_mode = JNI_ABORT)        -> raii_var<decltype(getJNIEnv()->GetByteArrayElements(bytes, nullptr))> {        using type = decltype(getJNIEnv()->GetByteArrayElements(bytes, nullptr));        assert(nullptr != bytes);        return raii_var<type>(                [bytes]()->type {                    jboolean isCopy;                    auto result=getJNIEnv()->GetByteArrayElements(bytes, &isCopy);                    assert(isCopy); // 调用成功断言                    return std::move(result);                },                [release_mode,bytes](type &obj) {getJNIEnv()->ReleaseByteArrayElements(bytes, obj, release_mode);});    }

raii_GetStringUTFChars

raii_GetStringUTFChars封装JNIEnv::GetStringUTFChars,返回java String的UTF-8字符串

    static auto raii_GetStringUTFChars(            jstring jstr) -> raii_var<decltype(getJNIEnv()->GetStringUTFChars(jstr, nullptr))> {        using type = decltype(getJNIEnv()->GetStringUTFChars(jstr, nullptr));        assert(nullptr != jstr);        return raii_var<type>([jstr]()->type {            jboolean isCopy;            auto result=getJNIEnv()->GetStringUTFChars(jstr, &isCopy);            assert(isCopy); // 调用成功断言                return std::move(result);            }, [jstr](type &obj) {getJNIEnv()->ReleaseStringUTFChars(jstr,obj);});    }

throwByName

throwByName抛出name指定类名的异常,msg为异常信息
throwIllegalArgumentException抛出 java.lang.IllegalArgumentException异常

void throwByName(const char* name, const char* msg) {    auto cls = raii_FindClass_LocalRef(name);    /* if cls is NULL, an exception has already been thrown */    if (cls.get() != nullptr) {        getJNIEnv()->ThrowNew(cls.get(), name);    } else {        throw invalid_argument(string("not found java class:").append(name).data());    }}void throwIllegalArgumentException(const char* msg) {    throwByName("java/lang/IllegalArgumentException", msg);}
0 0