用例证学习 c++范型编程(模板元)
用例子学习 c++范型编程(模板元)
此文版权属于作者所有,任何人、媒体或者网站转载、借用都必须征得作者本人同意!
例子用一个实例:通过 jni 接口读取 java 对象。
#include <jni.h> //============================================================= // 场景 1,最常见 namespace t1 { //============================================================= #if 0 // java 类 public class Frame { public int width = 0; public int height = 0; } #endif class Frame1 { public: jint width; jint height; }; //------------------------- void getFrame(JNIEnv* env, jobject jframe, Frame1& frame) { jclass cls = env->GetObjectClass(jframe); { jfieldID field = env->GetFieldID(cls, "width", "I"); frame.width = env->functions->GetIntField(env, jframe, field); } { jfieldID field = env->GetFieldID(cls, "height", "I"); frame.height = env->functions->GetIntField(env, jframe, field); } } //============================================================= // 修改 Frame 的数据成员 height 的类型,对应的代码修改如下 #if 0 // java 类 public class Frame { public int width = 0; public long height = 0; } #endif class Frame2 { public: jint width; jlong height; }; //------------------------- void getFrame(JNIEnv* env, jobject jframe, Frame2& frame) { jclass cls = env->GetObjectClass(jframe); { jfieldID field = env->GetFieldID(cls, "width", "I"); frame.width = env->functions->GetIntField(env, jframe, field); } { jfieldID field = env->GetFieldID(cls, "height", "J"); frame.height = env->functions->GetLongField(env, jframe, field); } } } // namespace t1 //============================================================= // 场景 2,比较常见 c 风格或者 c++ 风格 namespace t2 { #if 0 // Frame java implement public class Frame { public int width = 0; public long height = 0; } #endif class Frame { public: jint width; jlong height; }; //============================================================= // 最普通,最直白 void getFrame(JNIEnv* env, jobject jframe, Frame& frame) { jclass cls = env->GetObjectClass(jframe); { jfieldID field = env->GetFieldID(cls, "width", "I"); frame.width = env->functions->GetIntField(env, jframe, field); } { jfieldID field = env->GetFieldID(cls, "height", "J"); frame.height = env->functions->GetLongField(env, jframe, field); } } //============================================================= // c 风格 1 void getField_jint(JNIEnv* env, jobject jframe, char const* name, jint* v) { jclass cls = env->GetObjectClass(jframe); jfieldID field = env->GetFieldID(cls, name, "I"); *v = env->functions->GetIntField(env, jframe, field); } void getField_jlong(JNIEnv* env, jobject jframe, char const* name, jlong* v) { jclass cls = env->GetObjectClass(jframe); jfieldID field = env->GetFieldID(cls, name, "J"); *v = env->functions->GetLongField(env, jframe, field); } //------------------------- void getFrame2(JNIEnv* env, jobject jframe, Frame& frame) { getField_jint(env, jframe, "width", &frame.width); getField_jlong(env, jframe, "height", &frame.height); } //============================================================= // c 风格 2 enum FieldType{ FT_INT, FT_LONG, }; union Field { jint i; jlong l; }; void getField(JNIEnv* env, jobject jframe, char const* name, FieldType type, Field* v) { jclass cls = env->GetObjectClass(jframe); jfieldID field; switch(type) { case FT_INT: field = env->GetFieldID(cls, name, "I"); v->i = env->functions->GetIntField(env, jframe, field); break; case FT_LONG: field = env->GetFieldID(cls, name, "J"); v->l = env->functions->GetLongField(env, jframe, field); break; } } //------------------------- void getFrame3(JNIEnv* env, jobject jframe, Frame& frame) { Field v; getField(env, jframe, "width", FT_INT, &v); frame.width = v.i; getField(env, jframe, "height", FT_LONG, &v); frame.height = v.l; } //============================================================= // c++ 风格 void getField(JNIEnv* env, jobject jframe, char const* name, jint& v) { jclass cls = env->GetObjectClass(jframe); jfieldID field = env->GetFieldID(cls, name, "I"); v = env->functions->GetIntField(env, jframe, field); } void getField(JNIEnv* env, jobject jframe, char const* name, jlong& v) { jclass cls = env->GetObjectClass(jframe); jfieldID field = env->GetFieldID(cls, name, "J"); v = env->functions->GetLongField(env, jframe, field); } //------------------------- void getFrame4(JNIEnv* env, jobject jframe, Frame& frame) { getField(env, jframe, "width", frame.width); getField(env, jframe, "height", frame.height); } } // namespace t2 //============================================================= // 场景 3,现代 c++ 风格,采用范型编程实现 namespace t3 { #if 0 // Frame java implement public class Frame { public int width = 0; public long height = 0; } #endif class Frame { public: jint width; jlong height; }; template<typename T> class Field { public: static char const* SIGNATURE; static void GetField(JNIEnv* env, jobject obj, jfieldID field, T& v); }; template<> char const* Field<jint>::SIGNATURE = "I"; template<> inline void Field<jint>::GetField(JNIEnv* env, jobject obj, jfieldID field, jint& v) { v = env->functions->GetIntField(env, obj, field); } template<> char const* Field<jlong>::SIGNATURE = "J"; template<> inline void Field<jlong>::GetField(JNIEnv* env, jobject obj, jfieldID field, jlong& v) { v = env->functions->GetLongField(env, obj, field); } template<typename T> void getField(JNIEnv* env, jobject jframe, char const* name, T& v) { jclass cls = env->GetObjectClass(jframe); jfieldID field = env->GetFieldID(cls, name, Field<T>::SIGNATURE); Field<T>::GetField(env, jframe, field, v); v = env->functions->GetIntField(env, jframe, field); } //------------------------- void getFrame(JNIEnv* env, jobject jframe, Frame& frame) { getField(env, jframe, "width", frame.width); getField(env, jframe, "height", frame.height); } } // namespace t3