xref: /aosp_15_r20/external/fbjni/cxx/fbjni/detail/MetaConvert.h (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1*65c59e02SInna Palant /*
2*65c59e02SInna Palant  * Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palant  *
4*65c59e02SInna Palant  * Licensed under the Apache License, Version 2.0 (the "License");
5*65c59e02SInna Palant  * you may not use this file except in compliance with the License.
6*65c59e02SInna Palant  * You may obtain a copy of the License at
7*65c59e02SInna Palant  *
8*65c59e02SInna Palant  *     http://www.apache.org/licenses/LICENSE-2.0
9*65c59e02SInna Palant  *
10*65c59e02SInna Palant  * Unless required by applicable law or agreed to in writing, software
11*65c59e02SInna Palant  * distributed under the License is distributed on an "AS IS" BASIS,
12*65c59e02SInna Palant  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*65c59e02SInna Palant  * See the License for the specific language governing permissions and
14*65c59e02SInna Palant  * limitations under the License.
15*65c59e02SInna Palant  */
16*65c59e02SInna Palant 
17*65c59e02SInna Palant #pragma once
18*65c59e02SInna Palant 
19*65c59e02SInna Palant #include <jni.h>
20*65c59e02SInna Palant 
21*65c59e02SInna Palant #include "Common.h"
22*65c59e02SInna Palant #include "References.h"
23*65c59e02SInna Palant 
24*65c59e02SInna Palant namespace facebook {
25*65c59e02SInna Palant namespace jni {
26*65c59e02SInna Palant 
27*65c59e02SInna Palant namespace detail {
28*65c59e02SInna Palant 
29*65c59e02SInna Palant // In order to avoid potentially filling the jni locals table,
30*65c59e02SInna Palant // temporary objects (right now, this is just jstrings) need to be
31*65c59e02SInna Palant // released. This is done by returning a holder which autoconverts to
32*65c59e02SInna Palant // jstring.
33*65c59e02SInna Palant template <typename T>
callToJni(T && t)34*65c59e02SInna Palant inline T callToJni(T&& t) {
35*65c59e02SInna Palant   return t;
36*65c59e02SInna Palant }
37*65c59e02SInna Palant 
38*65c59e02SInna Palant template <typename T>
callToJni(local_ref<T> && sref)39*65c59e02SInna Palant inline JniType<T> callToJni(local_ref<T>&& sref) {
40*65c59e02SInna Palant   return sref.get();
41*65c59e02SInna Palant }
42*65c59e02SInna Palant 
43*65c59e02SInna Palant template <typename T>
toPlainJniReference(T obj)44*65c59e02SInna Palant enable_if_t<IsPlainJniReference<T>(), T> toPlainJniReference(T obj) {
45*65c59e02SInna Palant   return obj;
46*65c59e02SInna Palant }
47*65c59e02SInna Palant 
48*65c59e02SInna Palant template <typename T>
toPlainJniReference(T repr)49*65c59e02SInna Palant enable_if_t<IsJavaClassType<T>(), JniType<T>> toPlainJniReference(T repr) {
50*65c59e02SInna Palant   return ReprAccess<T>::get(repr);
51*65c59e02SInna Palant }
52*65c59e02SInna Palant 
53*65c59e02SInna Palant // Normally, pass through types unmolested.
54*65c59e02SInna Palant template <typename T, typename Enabled = void>
55*65c59e02SInna Palant struct Convert {
56*65c59e02SInna Palant   typedef T jniType;
fromJniConvert57*65c59e02SInna Palant   static jniType fromJni(jniType t) {
58*65c59e02SInna Palant     return t;
59*65c59e02SInna Palant   }
toJniRetConvert60*65c59e02SInna Palant   static jniType toJniRet(jniType t) {
61*65c59e02SInna Palant     return t;
62*65c59e02SInna Palant   }
toCallConvert63*65c59e02SInna Palant   static jniType toCall(jniType t) {
64*65c59e02SInna Palant     return t;
65*65c59e02SInna Palant   }
66*65c59e02SInna Palant };
67*65c59e02SInna Palant 
68*65c59e02SInna Palant // This is needed for return conversion
69*65c59e02SInna Palant template <>
70*65c59e02SInna Palant struct Convert<void> {
71*65c59e02SInna Palant   typedef void jniType;
72*65c59e02SInna Palant };
73*65c59e02SInna Palant 
74*65c59e02SInna Palant // jboolean is an unsigned char, not a bool. Allow it to work either way.
75*65c59e02SInna Palant template <>
76*65c59e02SInna Palant struct Convert<bool> {
77*65c59e02SInna Palant   typedef jboolean jniType;
78*65c59e02SInna Palant   static bool fromJni(jniType t) {
79*65c59e02SInna Palant     return t;
80*65c59e02SInna Palant   }
81*65c59e02SInna Palant   static jniType toJniRet(bool t) {
82*65c59e02SInna Palant     return t;
83*65c59e02SInna Palant   }
84*65c59e02SInna Palant   static jniType toCall(bool t) {
85*65c59e02SInna Palant     return t;
86*65c59e02SInna Palant   }
87*65c59e02SInna Palant };
88*65c59e02SInna Palant 
89*65c59e02SInna Palant // Sometimes (64-bit Android) jlong is "long long", but int64_t is "long".
90*65c59e02SInna Palant // Allow int64_t to work as jlong.
91*65c59e02SInna Palant template <typename T>
92*65c59e02SInna Palant struct Convert<
93*65c59e02SInna Palant     T,
94*65c59e02SInna Palant     typename std::enable_if<
95*65c59e02SInna Palant         (std::is_same<T, long long>::value ||
96*65c59e02SInna Palant          std::is_same<T, int64_t>::value) &&
97*65c59e02SInna Palant         !std::is_same<T, jlong>::value>::type> {
98*65c59e02SInna Palant   typedef jlong jniType;
99*65c59e02SInna Palant   static T fromJni(jniType t) {
100*65c59e02SInna Palant     return t;
101*65c59e02SInna Palant   }
102*65c59e02SInna Palant   static jniType toJniRet(T t) {
103*65c59e02SInna Palant     return t;
104*65c59e02SInna Palant   }
105*65c59e02SInna Palant   static jniType toCall(T t) {
106*65c59e02SInna Palant     return t;
107*65c59e02SInna Palant   }
108*65c59e02SInna Palant };
109*65c59e02SInna Palant 
110*65c59e02SInna Palant // convert to alias_ref<T> from T
111*65c59e02SInna Palant template <typename T>
112*65c59e02SInna Palant struct Convert<alias_ref<T>> {
113*65c59e02SInna Palant   typedef JniType<T> jniType;
114*65c59e02SInna Palant   static alias_ref<jniType> fromJni(jniType t) {
115*65c59e02SInna Palant     return wrap_alias(t);
116*65c59e02SInna Palant   }
117*65c59e02SInna Palant   static jniType toJniRet(alias_ref<jniType> t) {
118*65c59e02SInna Palant     return t.get();
119*65c59e02SInna Palant   }
120*65c59e02SInna Palant   static jniType toCall(const alias_ref<jniType>& t) {
121*65c59e02SInna Palant     return t.get();
122*65c59e02SInna Palant   }
123*65c59e02SInna Palant };
124*65c59e02SInna Palant 
125*65c59e02SInna Palant // convert return from local_ref<T>
126*65c59e02SInna Palant template <typename T>
127*65c59e02SInna Palant struct Convert<local_ref<T>> {
128*65c59e02SInna Palant   typedef JniType<T> jniType;
129*65c59e02SInna Palant   // No automatic synthesis of local_ref
130*65c59e02SInna Palant   static jniType toJniRet(local_ref<jniType> t) {
131*65c59e02SInna Palant     return t.release();
132*65c59e02SInna Palant   }
133*65c59e02SInna Palant   static jniType toCall(const local_ref<jniType>& t) {
134*65c59e02SInna Palant     return t.get();
135*65c59e02SInna Palant   }
136*65c59e02SInna Palant };
137*65c59e02SInna Palant 
138*65c59e02SInna Palant // convert return from global_ref<T>
139*65c59e02SInna Palant template <typename T>
140*65c59e02SInna Palant struct Convert<global_ref<T>> {
141*65c59e02SInna Palant   typedef JniType<T> jniType;
142*65c59e02SInna Palant   // No automatic synthesis of global_ref
143*65c59e02SInna Palant   static jniType toJniRet(global_ref<jniType>&& t) {
144*65c59e02SInna Palant     // If this gets called, ownership the global_ref was passed in here.  (It's
145*65c59e02SInna Palant     // probably a copy of a persistent global_ref made when a function was
146*65c59e02SInna Palant     // declared to return a global_ref, but it could moved out or otherwise not
147*65c59e02SInna Palant     // referenced elsewhere.  Doesn't matter.)  Either way, the only safe way
148*65c59e02SInna Palant     // to return it is to make a local_ref, release it, and return the
149*65c59e02SInna Palant     // underlying local jobject.
150*65c59e02SInna Palant     auto ret = make_local(t);
151*65c59e02SInna Palant     return ret.release();
152*65c59e02SInna Palant   }
153*65c59e02SInna Palant   static jniType toJniRet(const global_ref<jniType>& t) {
154*65c59e02SInna Palant     // If this gets called, the function was declared to return const&.  We
155*65c59e02SInna Palant     // have a ref to a global_ref whose lifetime will exceed this call, so we
156*65c59e02SInna Palant     // can just get the underlying jobject and return it to java without
157*65c59e02SInna Palant     // needing to make a local_ref.
158*65c59e02SInna Palant     return t.get();
159*65c59e02SInna Palant   }
160*65c59e02SInna Palant   static jniType toCall(const global_ref<jniType>& t) {
161*65c59e02SInna Palant     return t.get();
162*65c59e02SInna Palant   }
163*65c59e02SInna Palant };
164*65c59e02SInna Palant 
165*65c59e02SInna Palant template <typename T>
166*65c59e02SInna Palant struct jni_sig_from_cxx_t;
167*65c59e02SInna Palant template <typename R, typename... Args>
168*65c59e02SInna Palant struct jni_sig_from_cxx_t<R(Args...)> {
169*65c59e02SInna Palant   using JniRet = typename Convert<typename std::decay<R>::type>::jniType;
170*65c59e02SInna Palant   using JniSig =
171*65c59e02SInna Palant       JniRet(typename Convert<typename std::decay<Args>::type>::jniType...);
172*65c59e02SInna Palant };
173*65c59e02SInna Palant 
174*65c59e02SInna Palant template <typename T>
175*65c59e02SInna Palant using jni_sig_from_cxx = typename jni_sig_from_cxx_t<T>::JniSig;
176*65c59e02SInna Palant 
177*65c59e02SInna Palant } // namespace detail
178*65c59e02SInna Palant 
179*65c59e02SInna Palant template <typename R, typename... Args>
180*65c59e02SInna Palant struct jmethod_traits_from_cxx<R(Args...)>
181*65c59e02SInna Palant     : jmethod_traits<detail::jni_sig_from_cxx<R(Args...)>> {};
182*65c59e02SInna Palant 
183*65c59e02SInna Palant } // namespace jni
184*65c59e02SInna Palant } // namespace facebook
185