#ifndef mozilla_jni_Natives_h__ #define mozilla_jni_Natives_h__ #include #include "mozilla/jni/Accessors.h" #include "mozilla/jni/Refs.h" #include "mozilla/jni/Types.h" #include "mozilla/jni/Utils.h" namespace mozilla { namespace jni{ // Get the native pointer stored in a Java instance. template Impl* GetInstancePtr(JNIEnv* env, jobject instance) { // TODO: implement instance native pointers. return nullptr; } namespace detail { // Wrapper methods that convert arguments from the JNI types to the native // types, e.g. from jobject to jni::Object::Ref. For instance methods, the // wrapper methods also convert calls to calls on objects. // // We need specialization for static/non-static because the two have different // signatures (jobject vs jclass and Impl::*Method vs *Method). // We need specialization for return type, because void return type requires // us to not deal with the return value. template class NativeStubImpl; // Specialization for instance methods with non-void return type template class NativeStubImpl> { typedef typename Traits::Owner Owner; typedef typename TypeAdapter::JNIType ReturnJNIType; public: // Instance method template static ReturnJNIType Wrap(JNIEnv* env, jobject instance, typename TypeAdapter::JNIType... args) { Impl* const impl = GetInstancePtr(env, instance); if (!impl) { return ReturnJNIType(); } return TypeAdapter::FromNative(env, (impl->*Method)(TypeAdapter::ToNative(env, args)...)); } // Instance method with instance reference template static ReturnJNIType Wrap(JNIEnv* env, jobject instance, typename TypeAdapter::JNIType... args) { Impl* const impl = GetInstancePtr(env, instance); if (!impl) { return ReturnJNIType(); } return TypeAdapter::FromNative(env, (impl->*Method)(Owner::Ref::From(instance), TypeAdapter::ToNative(env, args)...)); } }; // Specialization for instance methods with void return type template class NativeStubImpl> { typedef typename Traits::Owner Owner; public: // Instance method template static void Wrap(JNIEnv* env, jobject instance, typename TypeAdapter::JNIType... args) { Impl* const impl = GetInstancePtr(env, instance); if (!impl) { return; } (impl->*Method)(TypeAdapter::ToNative(env, args)...); } // Instance method with instance reference template static void Wrap(JNIEnv* env, jobject instance, typename TypeAdapter::JNIType... args) { Impl* const impl = GetInstancePtr(env, instance); if (!impl) { return; } (impl->*Method)(Owner::Ref::From(instance), TypeAdapter::ToNative(env, args)...); } }; // Specialization for static methods with non-void return type template class NativeStubImpl> { typedef typename TypeAdapter::JNIType ReturnJNIType; public: // Static method template static ReturnJNIType Wrap(JNIEnv* env, jclass, typename TypeAdapter::JNIType... args) { return TypeAdapter::FromNative(env, (*Method)(TypeAdapter::ToNative(env, args)...)); } // Static method with class reference template static ReturnJNIType Wrap(JNIEnv* env, jclass cls, typename TypeAdapter::JNIType... args) { return TypeAdapter::FromNative(env, (*Method)(ClassObject::Ref::From(cls), TypeAdapter::ToNative(env, args)...)); } }; // Specialization for static methods with void return type template class NativeStubImpl> { public: // Static method template static void Wrap(JNIEnv* env, jclass, typename TypeAdapter::JNIType... args) { (*Method)(TypeAdapter::ToNative(env, args)...); } // Static method with class reference template static void Wrap(JNIEnv* env, jclass cls, typename TypeAdapter::JNIType... args) { (*Method)(ClassObject::Ref::From(cls), TypeAdapter::ToNative(env, args)...); } }; } // namespace detail // Form a stub wrapper from a native method's traits class and an implementing // class. The stub wrapper has a Wrap function that will form a wrapped stub. template struct NativeStub : detail::NativeStubImpl { }; // Generate a JNINativeMethod from a native // method's traits class and a wrapped stub. template constexpr JNINativeMethod MakeNativeMethod(Ret (*stub)(JNIEnv*, Args...)) { return { Traits::name, Traits::signature, reinterpret_cast(stub) }; } // Class inherited by implementing class. template class NativeImpl { typedef typename Cls::template Natives Natives; static bool sInited; public: static void Init() { if (sInited) { return; } JNIEnv* const env = GetJNIForThread(); env->RegisterNatives(Accessor::EnsureClassRef(env), Natives::methods, sizeof(Natives::methods) / sizeof(JNINativeMethod)); sInited = true; } NativeImpl() { // Initialize on creation if not already initialized. Init(); } }; // Define static member. template bool NativeImpl::sInited; } // namespace jni } // namespace mozilla #endif // mozilla_jni_Natives_h__