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

在上一节《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);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值