Files
flipper/libs/fbjni/cxx/fbjni/detail/MetaConvert.h
Pritesh Nandgaonkar 72045da4be Use the latest fbjni
2018-06-15 15:55:10 +01:00

151 lines
4.1 KiB
C++

/**
* Copyright 2004-present, Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <jni.h>
#include "Common.h"
#include "References.h"
namespace facebook {
namespace jni {
namespace detail {
// In order to avoid potentially filling the jni locals table,
// temporary objects (right now, this is just jstrings) need to be
// released. This is done by returning a holder which autoconverts to
// jstring.
template <typename T>
inline T callToJni(T&& t) {
return t;
}
template <typename T>
inline JniType<T> callToJni(local_ref<T>&& sref) {
return sref.get();
}
// Normally, pass through types unmolested.
template <typename T, typename Enabled = void>
struct Convert {
typedef T jniType;
static jniType fromJni(jniType t) {
return t;
}
static jniType toJniRet(jniType t) {
return t;
}
static jniType toCall(jniType t) {
return t;
}
};
// This is needed for return conversion
template <>
struct Convert<void> {
typedef void jniType;
};
// jboolean is an unsigned char, not a bool. Allow it to work either way.
template<>
struct Convert<bool> {
typedef jboolean jniType;
static bool fromJni(jniType t) {
return t;
}
static jniType toJniRet(bool t) {
return t;
}
static jniType toCall(bool t) {
return t;
}
};
// convert to alias_ref<T> from T
template <typename T>
struct Convert<alias_ref<T>> {
typedef JniType<T> jniType;
static alias_ref<jniType> fromJni(jniType t) {
return wrap_alias(t);
}
static jniType toJniRet(alias_ref<jniType> t) {
return t.get();
}
static jniType toCall(alias_ref<jniType> t) {
return t.get();
}
};
// convert return from local_ref<T>
template <typename T>
struct Convert<local_ref<T>> {
typedef JniType<T> jniType;
// No automatic synthesis of local_ref
static jniType toJniRet(local_ref<jniType> t) {
return t.release();
}
static jniType toCall(local_ref<jniType> t) {
return t.get();
}
};
// convert return from global_ref<T>
template <typename T>
struct Convert<global_ref<T>> {
typedef JniType<T> jniType;
// No automatic synthesis of global_ref
static jniType toJniRet(global_ref<jniType>&& t) {
// If this gets called, ownership the global_ref was passed in here. (It's
// probably a copy of a persistent global_ref made when a function was
// declared to return a global_ref, but it could moved out or otherwise not
// referenced elsewhere. Doesn't matter.) Either way, the only safe way
// to return it is to make a local_ref, release it, and return the
// underlying local jobject.
auto ret = make_local(t);
return ret.release();
}
static jniType toJniRet(const global_ref<jniType>& t) {
// If this gets called, the function was declared to return const&. We
// have a ref to a global_ref whose lifetime will exceed this call, so we
// can just get the underlying jobject and return it to java without
// needing to make a local_ref.
return t.get();
}
static jniType toCall(global_ref<jniType> t) {
return t.get();
}
};
template <typename T> struct jni_sig_from_cxx_t;
template <typename R, typename... Args>
struct jni_sig_from_cxx_t<R(Args...)> {
using JniRet = typename Convert<typename std::decay<R>::type>::jniType;
using JniSig = JniRet(typename Convert<typename std::decay<Args>::type>::jniType...);
};
template <typename T>
using jni_sig_from_cxx = typename jni_sig_from_cxx_t<T>::JniSig;
} // namespace detail
template <typename R, typename... Args>
struct jmethod_traits_from_cxx<R(Args...)> : jmethod_traits<detail::jni_sig_from_cxx<R(Args...)>> {
};
}}