Skip to content

Commit 54d1a56

Browse files
committed
Proxying now returns RefBase objects.
1 parent 40b9657 commit 54d1a56

File tree

3 files changed

+68
-34
lines changed

3 files changed

+68
-34
lines changed

implementation/overload_ref.h

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,31 @@
4141
#include "jni_dep.h"
4242
#include "metaprogramming/double_locked_value.h"
4343
#include "metaprogramming/string_concatenate.h"
44+
#include "implementation/id.h"
4445

4546
namespace jni {
47+
namespace detail {
48+
template <typename T>
49+
auto ForwardWithRefStripImpl(T&& t, std::true_type /* is_ref_base */) {
50+
using U = std::remove_reference_t<T>;
51+
using CastT = RefBaseStorageT_t<U>;
52+
return CastT(std::forward<T>(t)); // return by value, move or copy
53+
}
54+
55+
template <typename T>
56+
decltype(auto) ForwardWithRefStripImpl(
57+
T&& t, std::false_type /* not ref base */) {
58+
return std::forward<T>(t); // perfect forward
59+
}
60+
} // namespace detail
61+
62+
template <typename T>
63+
decltype(auto) ForwardWithRefStrip(T&& t) {
64+
using U = std::remove_reference_t<T>;
65+
return detail::ForwardWithRefStripImpl(
66+
std::forward<T>(t),
67+
std::is_base_of<RefBaseBase, U>{});
68+
}
4669

4770
// Transforms a OverloadRef IdT into a fully qualified ID. Storage is keyed
4871
// against these IDs to reduce excess MethodID lookups.
@@ -56,7 +79,7 @@ struct OverloadRefUniqueId {
5679
// Dashes are solely for readability in debugging.
5780
static constexpr std::string_view TypeName() {
5881
return metaprogramming::StringConcatenate_v<
59-
kClassQualifier, kDash, kOverloadName, kDash, Signature_v<IdT>>;
82+
kClassQualifier, kDash, kOverloadName, kDash, Signature_v<IdT>>;
6083
}
6184
};
6285

@@ -68,25 +91,25 @@ struct OverloadRef {
6891
using SelfIdT = typename IdT::template ChangeIdType<IdType::CLASS>;
6992

7093
using ReturnProxied = std::conditional_t<
71-
ReturnIdT::kIsSelf,
72-
Return_t<typename SelfIdT::MaterializeCDeclT, SelfIdT>,
73-
Return_t<typename ReturnIdT::MaterializeCDeclT, ReturnIdT>>;
94+
ReturnIdT::kIsSelf,
95+
Return_t<typename SelfIdT::MaterializeCDeclT, SelfIdT>,
96+
Return_t<typename ReturnIdT::MaterializeCDeclT, ReturnIdT>>;
7497

7598
static jmethodID GetMethodID(jclass clazz) {
7699
static auto get_lambda =
77100
[clazz](metaprogramming::DoubleLockedValue<jmethodID>* storage) {
78-
if (kConfiguration.release_method_ids_on_teardown_) {
79-
DefaultRefs<jmethodID>().push_back(storage);
80-
}
81-
82-
if constexpr (IdT::kIsStatic) {
83-
return jni::JniHelper::GetStaticMethodID(clazz, IdT::Name(),
84-
Signature_v<IdT>.data());
85-
} else {
86-
return jni::JniHelper::GetMethodID(clazz, IdT::Name(),
87-
Signature_v<IdT>.data());
88-
}
89-
};
101+
if (kConfiguration.release_method_ids_on_teardown_) {
102+
DefaultRefs<jmethodID>().push_back(storage);
103+
}
104+
105+
if constexpr (IdT::kIsStatic) {
106+
return jni::JniHelper::GetStaticMethodID(clazz, IdT::Name(),
107+
Signature_v<IdT>.data());
108+
} else {
109+
return jni::JniHelper::GetMethodID(clazz, IdT::Name(),
110+
Signature_v<IdT>.data());
111+
}
112+
};
90113

91114
return RefStorage<decltype(get_lambda), OverloadRefUniqueId<IdT>>::Get(
92115
get_lambda);
@@ -102,30 +125,36 @@ struct OverloadRef {
102125
if constexpr (std::is_same_v<ReturnProxied, void>) {
103126
return InvokeHelper<void, kRank, kStatic>::Invoke(
104127
object, clazz, mthd,
105-
Proxy_t<Params>::ProxyAsArg(std::forward<Params>(params))...);
128+
ForwardWithRefStrip(Proxy_t<Params>::ProxyAsArg(
129+
std::forward<Params>(params)))...);
106130
} else if constexpr (IdT::kIsConstructor) {
107131
return ReturnProxied{
108132
AdoptLocal{},
109133
LifecycleHelper<jobject, LifecycleType::LOCAL>::Construct(
110134
clazz, mthd,
111-
Proxy_t<Params>::ProxyAsArg(std::forward<Params>(params))...)};
135+
ForwardWithRefStrip(
136+
Proxy_t<Params>::ProxyAsArg(
137+
std::forward<Params>(params)))...)};
112138
} else {
113139
if constexpr (std::is_base_of_v<RefBaseBase, ReturnProxied>) {
114140
return ReturnProxied{
115141
AdoptLocal{},
116142
InvokeHelper<typename ReturnIdT::CDecl, kRank, kStatic>::Invoke(
117143
object, clazz, mthd,
118-
Proxy_t<Params>::ProxyAsArg(std::forward<Params>(params))...)};
144+
ForwardWithRefStrip(
145+
Proxy_t<Params>::ProxyAsArg(std::forward<Params>(params)))
146+
...)};
119147
} else {
120148
return static_cast<ReturnProxied>(
121-
InvokeHelper<typename ReturnIdT::CDecl, kRank, kStatic>::Invoke(
122-
object, clazz, mthd,
123-
Proxy_t<Params>::ProxyAsArg(std::forward<Params>(params))...));
149+
InvokeHelper<typename ReturnIdT::CDecl, kRank, kStatic>::Invoke(
150+
object, clazz, mthd,
151+
ForwardWithRefStrip(
152+
Proxy_t<Params>::ProxyAsArg(
153+
std::forward<Params>(params)))...));
124154
}
125155
}
126156
}
127157
};
158+
} // namespace jni
128159

129-
} // namespace jni
130-
131-
#endif // JNI_BIND_OVERLOAD_REF_H
160+
#endif // JNI_BIND_OVERLOAD_REF_H

implementation/proxy_definitions_string.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "jni_dep.h"
3838

3939
namespace jni {
40-
4140
template <typename JString>
4241
struct Proxy<JString,
4342
typename std::enable_if_t<std::is_same_v<JString, jstring>>>
@@ -72,18 +71,20 @@ struct Proxy<JString,
7271
// correctly release local instances, but here we are stripping that so it can
7372
// be used in a method. This could be obviated by wrapping the calling scope
7473
// in a local stack frame.
75-
static jstring ProxyAsArg(jstring s) { return s; }
74+
static RefBase<jstring> ProxyAsArg(jstring s) {
75+
return {s};
76+
}
7677

7778
template <typename T,
7879
typename = std::enable_if_t<std::is_same_v<T, const char*> ||
7980
std::is_same_v<T, std::string> ||
8081
std::is_same_v<T, std::string_view>>>
81-
static jstring ProxyAsArg(T s) {
82+
static RefBase<jstring> ProxyAsArg(T s) {
8283
if constexpr (std::is_same_v<T, const char*>) {
83-
return LifecycleHelper<jstring, LifecycleType::LOCAL>::Construct(s);
84+
return {LifecycleHelper<jstring, LifecycleType::LOCAL>::Construct(s)};
8485
} else {
85-
return LifecycleHelper<jstring, LifecycleType::LOCAL>::Construct(
86-
s.data());
86+
return {LifecycleHelper<jstring, LifecycleType::LOCAL>::Construct(
87+
s.data())};
8788
}
8889
}
8990

@@ -101,7 +102,6 @@ struct Proxy<JString,
101102
return t.Release();
102103
}
103104
};
104-
105-
} // namespace jni
105+
} // namespace jni
106106

107107
#endif // JNI_BIND_IMPLEMENTATION_PROXY_DEFINITIONS_STRING_H_

implementation/ref_base.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ struct RefBaseBase {};
3030
// Used to detect RefBase in type proxying.
3131
// This is useful, e.g. when you want to say "an object that might be passed"
3232
// but the object's type (i.e. full name + loader information) is unknown.
33-
template <typename StorageType>
33+
template <typename StorageType_>
3434
class RefBase : public RefBaseBase {
3535
public:
3636
template <typename Base, LifecycleType lifecycleType, typename JniT,
3737
typename ViableSpan>
3838
friend struct EntryBase;
3939

40+
using StorageType = StorageType_;
41+
4042
RefBase(StorageType object) : object_ref_(object) {}
4143

4244
RefBase(const RefBase& rhs) = delete;
@@ -67,6 +69,9 @@ class RefBase : public RefBaseBase {
6769
template <typename T>
6870
using RefBaseT_t = typename T::RefBaseT;
6971

72+
template <typename T>
73+
using RefBaseStorageT_t = typename T::StorageType;
74+
7075
} // namespace jni
7176

7277
#endif // JNI_BIND_REF_BASE_H_

0 commit comments

Comments
 (0)