Skip to content

Commit 9ce08b1

Browse files
committed
Support arguments for native peer initializers
1 parent a2e71d9 commit 9ce08b1

File tree

3 files changed

+58
-21
lines changed

3 files changed

+58
-21
lines changed

examples/native_peer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)
88
{
99
static constexpr auto Name() { return "Calculator"; }
1010

11-
Calculator() { std::cout << "Native peer initialized" << std::endl; }
11+
Calculator(JNIEnv&) { std::cout << "Native peer initialized" << std::endl; }
1212
~Calculator() { std::cout << "Native peer finalized" << std::endl; }
1313

1414
jni::jlong Add(jni::JNIEnv&, jni::jlong a, jni::jlong b) { return a + b; }
@@ -20,7 +20,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)
2020
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
2121

2222
jni::RegisterNativePeer<Calculator>(env, jni::Class<Calculator>::Find(env), "peer",
23-
std::make_unique<Calculator>,
23+
std::make_unique<Calculator, JNIEnv&>,
2424
"initialize",
2525
"finalize",
2626
METHOD(&Calculator::Add, "add"),

include/jni/native_method.hpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -285,33 +285,56 @@ namespace jni
285285
RegisterNatives(env, clazz, methods.template operator()<Peer>(field)...);
286286
}
287287

288-
template < class Peer, class TagType, class Constructor, class... Methods >
288+
template < class Peer, class TagType, class >
289+
struct NativePeerHelper;
290+
291+
template < class Peer, class TagType, class... Args >
292+
struct NativePeerHelper< Peer, TagType, std::unique_ptr<Peer> (JNIEnv&, Args...) >
293+
{
294+
using UniquePeer = std::unique_ptr<Peer>;
295+
using Initializer = UniquePeer (JNIEnv&, Args...);
296+
297+
auto MakeInitializer(const Field<TagType, jlong>& field, const char* name, Initializer* initializer) const
298+
{
299+
auto wrapper = [field, initializer] (JNIEnv& e, Object<TagType> obj, std::decay_t<Args>... args)
300+
{
301+
UniquePeer previous(reinterpret_cast<Peer*>(obj.Get(e, field)));
302+
UniquePeer instance(initializer(e, std::move(args)...));
303+
obj.Set(e, field, reinterpret_cast<jlong>(instance.get()));
304+
instance.release();
305+
};
306+
307+
return MakeNativeMethod(name, wrapper);
308+
}
309+
310+
auto MakeFinalizer(const Field<TagType, jlong>& field, const char* name) const
311+
{
312+
auto wrapper = [field] (JNIEnv& e, Object<TagType> obj)
313+
{
314+
UniquePeer instance(reinterpret_cast<Peer*>(obj.Get(e, field)));
315+
if (instance) obj.Set(e, field, jlong(0));
316+
instance.reset();
317+
};
318+
319+
return MakeNativeMethod(name, wrapper);
320+
}
321+
};
322+
323+
template < class Peer, class TagType, class Initializer, class... Methods >
289324
void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName,
290-
Constructor constructor,
325+
Initializer initialize,
291326
const char* initializeMethodName,
292327
const char* finalizeMethodName,
293328
Methods&&... methods)
294329
{
295330
static Field<TagType, jlong> field { env, clazz, fieldName };
296331

297-
auto finalize = [] (JNIEnv& e, Object<TagType> obj)
298-
{
299-
std::unique_ptr<Peer> instance(reinterpret_cast<Peer*>(obj.Get(e, field)));
300-
if (instance) obj.Set(e, field, jlong(0));
301-
instance.reset();
302-
};
303-
304-
auto initialize = [constructor] (JNIEnv& e, Object<TagType> obj)
305-
{
306-
std::unique_ptr<Peer> previous(reinterpret_cast<Peer*>(obj.Get(e, field)));
307-
std::unique_ptr<Peer> instance(constructor());
308-
obj.Set(e, field, reinterpret_cast<jlong>(instance.get()));
309-
instance.release();
310-
};
332+
using InitializerMethodType = typename NativeMethodTraits<Initializer>::Type;
333+
NativePeerHelper<Peer, TagType, InitializerMethodType> helper;
311334

312335
RegisterNatives(env, clazz,
313-
MakeNativeMethod(initializeMethodName, initialize),
314-
MakeNativeMethod(finalizeMethodName, finalize),
336+
helper.MakeInitializer(field, initializeMethodName, initialize),
337+
helper.MakeFinalizer(field, finalizeMethodName),
315338
methods.template operator()<Peer>(field)...);
316339
}
317340
}

test/high_level.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace
1414

1515
struct Peer
1616
{
17+
Peer() {}
18+
Peer(jni::JNIEnv&, jni::jboolean) {}
1719
jni::jboolean True(jni::JNIEnv&) { return jni::jni_true; }
1820
jni::jboolean False(jni::JNIEnv&) { return jni::jni_false; }
1921
void Void(jni::JNIEnv&, jni::jboolean b) { assert(b == jni::jni_true); }
@@ -746,7 +748,7 @@ int main()
746748
env.functions->RegisterNatives = [] (JNIEnv*, jclass, const JNINativeMethod* m, jint len) -> jint
747749
{
748750
assert(len == 6);
749-
std::copy(m, m + 6, methods);
751+
std::copy(m, m + len, methods);
750752
return JNI_OK;
751753
};
752754

@@ -767,5 +769,17 @@ int main()
767769
assert(reinterpret_cast<jboolean (*)(JNIEnv&, jobject)>(methods[1].fnPtr)(env, jni::Unwrap(objectValue.Ptr())) == jni::jni_false);
768770
reinterpret_cast<void (*)(JNIEnv&, jobject, jboolean)>(methods[2].fnPtr)(env, jni::Unwrap(objectValue.Ptr()), jni::jni_true);
769771

772+
jni::RegisterNativePeer<Peer>(env, testClass, "peer",
773+
std::make_unique<Peer, jni::JNIEnv&, jni::jboolean>,
774+
"initialize",
775+
"finalize",
776+
METHOD("true", &Peer::True),
777+
METHOD("false", &Peer::False),
778+
METHOD("void", &Peer::Void),
779+
jni::MakeNativePeerMethod("static", [] (JNIEnv&, Peer&) {}));
780+
781+
assert(methods[0].name == std::string("initialize"));
782+
assert(methods[1].name == std::string("finalize"));
783+
770784
return 0;
771785
}

0 commit comments

Comments
 (0)