c++ - 如何使用 C++ 模板实现从类型到对象方法调用的映射?

标签 c++ templates jniwrapper

我想使用 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 的功能改进我的代码?

最佳答案

您可以将指向成员的指针添加到您的特征中。

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);
}

关于c++ - 如何使用 C++ 模板实现从类型到对象方法调用的映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51749136/

相关文章:

c++ - GCC- 无效使用 Register

c++ - std::pair 作为模板<class> 参数? C++

c++ - 如何调整由两点定义的线的大小,使其受 C++ 中的最大线长度约束

c++ - 我需要一个测试用例来证明我的算法/代码是错误的

C++如何使用其中也包含此类的类中的枚举

c++ - (重新)命名 std::pair 成员

java - 如果 `jobject` 代表同一个 Java 实例,它是否总是具有相同的地址?

java - 为什么当我在 64 位 jvm 中打开带有小程序的页面时 IE 11 会崩溃,但在 32 位 jvm 中却可以正常工作?

android - FFmpeg:对 'main' 的 undefined reference

c++ - 将 MFC 形式 'text' 作为 char 类型或常规字符串类型处理