Loading...
Searching...
No Matches
native_method.hpp
Go to the documentation of this file.
#pragma once
#include <jni/types.hpp>
#include <jni/errors.hpp>
#include <jni/functions.hpp>
#include <jni/tagging.hpp>
#include <jni/class.hpp>
#include <jni/object.hpp>
#include <exception>
#include <type_traits>
namespace jni
{
template < class M, class Enable = void >
struct NativeMethodTraits;
template < class R, class... Args >
struct NativeMethodTraits< R (Args...) >
{
using Type = R (Args...);
using ResultType = R;
};
template < class R, class... Args >
struct NativeMethodTraits< R (*)(Args...) >
: NativeMethodTraits< R (Args...) > {};
template < class T, class R, class... Args >
struct NativeMethodTraits< R (T::*)(Args...) const >
: NativeMethodTraits< R (Args...) > {};
template < class T, class R, class... Args >
struct NativeMethodTraits< R (T::*)(Args...) >
: NativeMethodTraits< R (Args...) > {};
template < class M >
struct NativeMethodTraits< M, std::enable_if_t< std::is_class<M>::value > >
: NativeMethodTraits< decltype(&M::operator()) > {};
template < class M >
auto MakeNativeMethod(const char* name, const char* sig, const M& m,
std::enable_if_t< std::is_class<M>::value >* = nullptr)
{
using FunctionType = typename NativeMethodTraits<M>::Type;
using ResultType = typename NativeMethodTraits<M>::ResultType;
static FunctionType* method = m;
auto wrapper = [] (JNIEnv* env, auto... args)
{
try
{
return method(env, args...);
}
catch (...)
{
ThrowJavaError(*env, std::current_exception());
return ResultType();
}
};
return JNINativeMethod< FunctionType > { name, sig, wrapper };
}
template < class M, M method >
auto MakeNativeMethod(const char* name, const char* sig)
{
using FunctionType = typename NativeMethodTraits<M>::Type;
using ResultType = typename NativeMethodTraits<M>::ResultType;
auto wrapper = [] (JNIEnv* env, auto... args)
{
try
{
return method(env, args...);
}
catch (...)
{
ThrowJavaError(*env, std::current_exception());
return ResultType();
}
};
return JNINativeMethod< FunctionType > { name, sig, wrapper };
}
template < class T, T*... >
struct NativeMethodMaker;
template < class T, class R, class Subject, class... Args >
struct NativeMethodMaker< R (T::*)(JNIEnv&, Subject, Args...) const >
{
template < class M >
auto operator()(const char* name, const M& m)
{
static M method(m);
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
{
return ReleaseUnique(method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...));
};
return MakeNativeMethod(name, TypeSignature<RemoveUniqueType<R> (std::decay_t<Args>...)>()(), wrapper);
}
};
template < class T, class Subject, class... Args >
struct NativeMethodMaker< void (T::*)(JNIEnv&, Subject, Args...) const >
{
template < class M >
auto operator()(const char* name, const M& m)
{
static M method(m);
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
{
method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...);
};
return MakeNativeMethod(name, TypeSignature<void (std::decay_t<Args>...)>()(), wrapper);
}
};
template < class M >
auto MakeNativeMethod(const char* name, const M& m)
{
return NativeMethodMaker<decltype(&M::operator())>()(name, m);
}
template < class R, class Subject, class... Args, R (*method)(JNIEnv&, Subject, Args...) >
struct NativeMethodMaker< R (JNIEnv&, Subject, Args...), method >
{
auto operator()(const char* name)
{
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
{
return ReleaseUnique(method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...));
};
return MakeNativeMethod(name, TypeSignature<RemoveUniqueType<R> (std::decay_t<Args>...)>()(), wrapper);
}
};
template < class Subject, class... Args, void (*method)(JNIEnv&, Subject, Args...) >
struct NativeMethodMaker< void (JNIEnv&, Subject, Args...), method >
{
auto operator()(const char* name)
{
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
{
method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...);
};
return MakeNativeMethod(name, TypeSignature<void (std::decay_t<Args>...)>()(), wrapper);
}
};
template < class M, M method >
auto MakeNativeMethod(const char* name)
{
using FunctionType = typename NativeMethodTraits<M>::Type;
return NativeMethodMaker<FunctionType, method>()(name);
}
template < class L, class >
class NativePeerLambdaMethod;
template < class L, class R, class P, class... Args >
class NativePeerLambdaMethod< L, R (L::*)(JNIEnv&, P&, Args...) const >
{
private:
const char* name;
L lambda;
public:
NativePeerLambdaMethod(const char* n, const L& l)
: name(n), lambda(l)
{}
template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > >
auto operator()(const Field<TagType, jlong>& field)
{
auto wrapper = [field, lambda = lambda] (JNIEnv& env, Object<TagType>& obj, Args... args)
{
return lambda(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...);
};
return MakeNativeMethod(name, wrapper);
}
};
template < class L >
auto MakeNativePeerMethod(const char* name, const L& lambda,
std::enable_if_t< std::is_class<L>::value >* = nullptr)
{
return NativePeerLambdaMethod<L, decltype(&L::operator())>(name, lambda);
}
template < class M, M* >
class NativePeerFunctionPointerMethod;
template < class R, class P, class... Args, R (*method)(JNIEnv&, P&, Args...) >
class NativePeerFunctionPointerMethod< R (JNIEnv&, P&, Args...), method >
{
private:
const char* name;
public:
NativePeerFunctionPointerMethod(const char* n)
: name(n)
{}
template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > >
auto operator()(const Field<TagType, jlong>& field)
{
auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args)
{
return method(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...);
};
return MakeNativeMethod(name, wrapper);
}
};
template < class M, M method >
auto MakeNativePeerMethod(const char* name,
std::enable_if_t< !std::is_member_function_pointer<M>::value >* = nullptr)
{
using FunctionType = typename NativeMethodTraits<M>::Type;
return NativePeerFunctionPointerMethod<FunctionType, method>(name);
}
template < class M, M >
class NativePeerMemberFunctionMethod;
template < class R, class P, class... Args, R (P::*method)(JNIEnv&, Args...) >
class NativePeerMemberFunctionMethod< R (P::*)(JNIEnv&, Args...), method >
{
private:
const char* name;
public:
NativePeerMemberFunctionMethod(const char* n)
: name(n)
{}
template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > >
auto operator()(const Field<TagType, jlong>& field)
{
auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args)
{
return (reinterpret_cast<P*>(obj.Get(env, field))->*method)(env, args...);
};
return MakeNativeMethod(name, wrapper);
}
};
template < class M, M method >
auto MakeNativePeerMethod(const char* name,
std::enable_if_t< std::is_member_function_pointer<M>::value >* = nullptr)
{
return NativePeerMemberFunctionMethod<M, method>(name);
}
template < class Peer, class TagType, class... Methods >
void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName, Methods&&... methods)
{
static Field<TagType, jni::jlong> field { env, clazz, fieldName };
RegisterNatives(env, *clazz, methods.template operator()<Peer>(field)...);
}
template < class Peer, class TagType, class >
struct NativePeerHelper;
template < class Peer, class TagType, class... Args >
struct NativePeerHelper< Peer, TagType, std::unique_ptr<Peer> (JNIEnv&, Args...) >
{
using UniquePeer = std::unique_ptr<Peer>;
using Initializer = UniquePeer (JNIEnv&, Args...);
auto MakeInitializer(const Field<TagType, jlong>& field, const char* name, Initializer* initializer) const
{
auto wrapper = [field, initializer] (JNIEnv& e, Object<TagType>& obj, std::decay_t<Args>&... args)
{
UniquePeer previous(reinterpret_cast<Peer*>(obj.Get(e, field)));
UniquePeer instance(initializer(e, args...));
obj.Set(e, field, reinterpret_cast<jlong>(instance.get()));
instance.release();
};
return MakeNativeMethod(name, wrapper);
}
auto MakeFinalizer(const Field<TagType, jlong>& field, const char* name) const
{
auto wrapper = [field] (JNIEnv& e, Object<TagType>& obj)
{
UniquePeer instance(reinterpret_cast<Peer*>(obj.Get(e, field)));
if (instance) obj.Set(e, field, jlong(0));
instance.reset();
};
return MakeNativeMethod(name, wrapper);
}
};
template < class Peer, class TagType, class Initializer, class... Methods >
void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName,
Initializer initialize,
const char* initializeMethodName,
const char* finalizeMethodName,
Methods&&... methods)
{
static Field<TagType, jlong> field { env, clazz, fieldName };
using InitializerMethodType = typename NativeMethodTraits<Initializer>::Type;
NativePeerHelper<Peer, TagType, InitializerMethodType> helper;
RegisterNatives(env, *clazz,
helper.MakeInitializer(field, initializeMethodName, initialize),
helper.MakeFinalizer(field, finalizeMethodName),
methods.template operator()<Peer>(field)...);
}
// Like std::make_unique, but with non-universal reference arguments, so it can be
// explicitly specialized (jni::MakePeer<Peer, jni::jboolean, ...>).
template < class Peer, class... Args >
std::unique_ptr<Peer> MakePeer(jni::JNIEnv& env, Args... args)
{
return std::make_unique<Peer>(env, args...);
}
}
class.hpp
jni::Class
Definition class.hpp:18
jni::Field
Definition field.hpp:13
jni::NativePeerFunctionPointerMethod< R(JNIEnv &, P &, Args...), method >::NativePeerFunctionPointerMethod
NativePeerFunctionPointerMethod(const char *n)
Definition native_method.hpp:228
jni::NativePeerFunctionPointerMethod< R(JNIEnv &, P &, Args...), method >::operator()
auto operator()(const Field< TagType, jlong > &field)
Definition native_method.hpp:233
jni::NativePeerFunctionPointerMethod
High-level peer, function pointer.
Definition native_method.hpp:219
jni::NativePeerLambdaMethod< L, R(L::*)(JNIEnv &, P &, Args...) const >::operator()
auto operator()(const Field< TagType, jlong > &field)
Definition native_method.hpp:197
jni::NativePeerLambdaMethod< L, R(L::*)(JNIEnv &, P &, Args...) const >::NativePeerLambdaMethod
NativePeerLambdaMethod(const char *n, const L &l)
Definition native_method.hpp:192
jni::NativePeerLambdaMethod
High-level peer, lambda.
Definition native_method.hpp:182
jni::NativePeerMemberFunctionMethod< R(P::*)(JNIEnv &, Args...), method >::operator()
auto operator()(const Field< TagType, jlong > &field)
Definition native_method.hpp:270
jni::NativePeerMemberFunctionMethod< R(P::*)(JNIEnv &, Args...), method >::NativePeerMemberFunctionMethod
NativePeerMemberFunctionMethod(const char *n)
Definition native_method.hpp:265
jni::NativePeerMemberFunctionMethod
High-level peer, member function pointer.
Definition native_method.hpp:256
jni::Object
Definition object.hpp:45
errors.hpp
functions.hpp
jni
Definition advanced_ownership.hpp:6
jni::UntaggedType
decltype(Untag(std::declval< T >())) UntaggedType
Definition tagging.hpp:130
jni::Tag
auto Tag(JNIEnv &, T primitive) -> std::enable_if_t< IsPrimitive< T >::value, T >
Definition tagging.hpp:94
jni::ThrowJavaError
void ThrowJavaError(JNIEnv &env, std::exception_ptr e)
Definition errors.hpp:101
jni::RegisterNativePeer
void RegisterNativePeer(JNIEnv &env, const Class< TagType > &clazz, const char *fieldName, Methods &&... methods)
Definition native_method.hpp:311
jni::AsLvalue
T & AsLvalue(T &&x)
Definition traits.hpp:33
jni::MakeNativePeerMethod
auto MakeNativePeerMethod(const char *name, const L &lambda, std::enable_if_t< std::is_class< L >::value > *=nullptr)
Definition native_method.hpp:209
jni::RegisterNatives
void RegisterNatives(JNIEnv &env, jclass &clazz, const Methods &... methods)
Definition functions.hpp:573
jni::ReleaseUnique
auto ReleaseUnique(T primitive)
Definition unique.hpp:143
jni::MakeNativeMethod
auto MakeNativeMethod(const char *name, const char *sig, const M &m, std::enable_if_t< std::is_class< M >::value > *=nullptr)
Low-level, lambda.
Definition native_method.hpp:45
jni::MakePeer
std::unique_ptr< Peer > MakePeer(jni::JNIEnv &env, Args... args)
Definition native_method.hpp:373
jni::RemoveUniqueType
typename RemoveUnique< T >::Type RemoveUniqueType
Definition unique.hpp:139
std
Definition errors.hpp:10
object.hpp
jni::JNINativeMethod
Definition types.hpp:64
jni::NativeMethodMaker< R(JNIEnv &, Subject, Args...), method >::operator()
auto operator()(const char *name)
Definition native_method.hpp:146
jni::NativeMethodMaker< R(T::*)(JNIEnv &, Subject, Args...) const >::operator()
auto operator()(const char *name, const M &m)
Definition native_method.hpp:104
jni::NativeMethodMaker< void(JNIEnv &, Subject, Args...), method >::operator()
auto operator()(const char *name)
Definition native_method.hpp:160
jni::NativeMethodMaker< void(T::*)(JNIEnv &, Subject, Args...) const >::operator()
auto operator()(const char *name, const M &m)
Definition native_method.hpp:121
jni::NativeMethodMaker
High-level, lambda.
Definition native_method.hpp:98
jni::NativeMethodTraits< R(Args...) >::ResultType
R ResultType
Definition native_method.hpp:22
jni::NativeMethodTraits< R(Args...) >::Type
R(Args...) Type
Definition native_method.hpp:21
jni::NativeMethodTraits
Definition native_method.hpp:16
jni::NativePeerHelper< Peer, TagType, std::unique_ptr< Peer >(JNIEnv &, Args...) >::MakeInitializer
auto MakeInitializer(const Field< TagType, jlong > &field, const char *name, Initializer *initializer) const
Definition native_method.hpp:326
jni::NativePeerHelper< Peer, TagType, std::unique_ptr< Peer >(JNIEnv &, Args...) >::Initializer
UniquePeer(JNIEnv &, Args...) Initializer
Definition native_method.hpp:324
jni::NativePeerHelper< Peer, TagType, std::unique_ptr< Peer >(JNIEnv &, Args...) >::UniquePeer
std::unique_ptr< Peer > UniquePeer
Definition native_method.hpp:323
jni::NativePeerHelper< Peer, TagType, std::unique_ptr< Peer >(JNIEnv &, Args...) >::MakeFinalizer
auto MakeFinalizer(const Field< TagType, jlong > &field, const char *name) const
Definition native_method.hpp:339
jni::NativePeerHelper
Definition native_method.hpp:318
jni::TypeSignature
Definition tagging.hpp:13
tagging.hpp
types.hpp