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