如何使用 C++ 模板实现从类型到对象方法调用的映射?
Posted
技术标签:
【中文标题】如何使用 C++ 模板实现从类型到对象方法调用的映射?【英文标题】:How to implement mapping from type to object method call using C++ templates? 【发布时间】:2018-08-08 14:24:55 【问题描述】:我想使用 C++ 模板为 JNI 代码中的 java 数组开发(又一个)包装器。主要目标是提高我的 C++ 模板编程技能。
我使用 android NDK 编译代码(编译器是 Clang 6.0.2)
到目前为止我已经做到了:
#include <jni.h>
template <typename T>
struct TypeToObjectType;
template <>
struct TypeToObjectType<jbyteArray>
typedef jbyte type;
;
template <>
struct TypeToObjectType<jintArray>
typedef jint type;
;
template <typename javaArrayT, typename nativeT>
class Java_array
JNIEnv *env;
jboolean is_copy;
jsize array_len;
javaArrayT array;
typename TypeToObjectType<javaArrayT>::type *array_elements;
public:
Java_array(JNIEnv *_env, javaArrayT _array)
: env(_env)
, array(_array)
, array_len(-1)
array_elements = env->GetByteArrayElements(array, &is_copy); //TODO: make it resolving automatically to other primitives
~Java_array()
env->ReleaseByteArrayElements(array, array_elements, JNI_ABORT);
jsize len()
if (array_len < 0)
array_len = env->GetArrayLength(array);
return array_len;
operator nativeT* () const
return reinterpret_cast<nativeT*>(array_elements);
;
;
这不适用于int[]
、float[]
和除byte[]
之外的其他数组,因为此类调用GetByteArrayElements
。
我使用struct TypeToObjectType
建立映射jbyteArray
-> jbyte
, jintArray
-> jint
。
此映射缺少部分 java 类型 -> JEnv
方法调用,即 jbyteArray
-> (GetByteArrayElements
, ReleaseByteArrayElements
), jintArray
-> (GetIntArrayElements
, ReleaseIntArrayElements
)`
我该怎么做?
如何使用 C++11、C++14 的功能改进我的代码?
【问题讨论】:
【参考方案1】:您可以将指向成员的指针添加到您的 trait。
template <>
struct TypeToObjectType<jbyteArray>
typedef jbyte type;
static constexpr jbyte * (JNIEnv::* const GetElements)(jbyteArray, jboolean *) = &JNIEnv::GetByteArrayElements;
static constexpr void (JNIEnv::* const ReleaseElements)(jbyteArray, jbyte *, decltype(JNI_ABORT)) = &JNIEnv::ReleaseByteArrayElements;
;
template <>
struct TypeToObjectType<jintArray>
typedef jint type;
static constexpr jint * (JNIEnv::* const GetElements)(jintArray, jboolean *) = &JNIEnv::GetIntArrayElements;
static constexpr void (JNIEnv::* const ReleaseElements)(jintArray, jint *, decltype(JNI_ABORT)) = &JNIEnv::ReleaseIntArrayElements;
;
你通过稍微不同的语法调用它
Java_array(JNIEnv *_env, javaArrayT _array)
: env(_env)
, array(_array)
, array_len(-1)
array_elements = (env->*TypeToObjectType<javaArrayT>::GetElements)(array, &is_copy);
~Java_array()
(env->*TypeToObjectType<javaArrayT>::ReleaseElements)(array, array_elements, JNI_ABORT);
【讨论】:
啊,对不起,我搞砸了如何声明指针 const,而不是函数返回类型。语法相当晦涩以上是关于如何使用 C++ 模板实现从类型到对象方法调用的映射?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 FreeMarker 模板调用对象的 java 方法?