mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1178850 - Add supporting classes for native JNI calls; r=snorp
This commit is contained in:
parent
6dd55e4405
commit
1f1f6ebea0
@ -33,16 +33,18 @@ struct Value
|
|||||||
|
|
||||||
// Base class for Method<>, Field<>, and Constructor<>.
|
// Base class for Method<>, Field<>, and Constructor<>.
|
||||||
class Accessor {
|
class Accessor {
|
||||||
private:
|
public:
|
||||||
template<class Cls>
|
template<class Cls>
|
||||||
static void EnsureClassRef(JNIEnv* env)
|
static jclass EnsureClassRef(JNIEnv* env)
|
||||||
{
|
{
|
||||||
if (!Cls::sClassRef) {
|
if (!Cls::sClassRef) {
|
||||||
MOZ_ALWAYS_TRUE(Cls::sClassRef =
|
MOZ_ALWAYS_TRUE(Cls::sClassRef =
|
||||||
AndroidBridge::GetClassGlobalRef(env, Cls::name));
|
AndroidBridge::GetClassGlobalRef(env, Cls::name));
|
||||||
}
|
}
|
||||||
|
return Cls::sClassRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
static void GetNsresult(JNIEnv* env, nsresult* rv)
|
static void GetNsresult(JNIEnv* env, nsresult* rv)
|
||||||
{
|
{
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
|
212
widget/android/jni/Natives.h
Normal file
212
widget/android/jni/Natives.h
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
#ifndef mozilla_jni_Natives_h__
|
||||||
|
#define mozilla_jni_Natives_h__
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#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<class Impl>
|
||||||
|
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<bool IsStatic, typename ReturnType,
|
||||||
|
class Traits, class Impl, class Args>
|
||||||
|
class NativeStubImpl;
|
||||||
|
|
||||||
|
// Specialization for instance methods with non-void return type
|
||||||
|
template<typename ReturnType, class Traits, class Impl, typename... Args>
|
||||||
|
class NativeStubImpl<false, ReturnType, Traits, Impl, jni::Args<Args...>>
|
||||||
|
{
|
||||||
|
typedef typename Traits::Owner Owner;
|
||||||
|
typedef typename TypeAdapter<ReturnType>::JNIType ReturnJNIType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Instance method
|
||||||
|
template<ReturnType (Impl::*Method) (Args...)>
|
||||||
|
static ReturnJNIType Wrap(JNIEnv* env, jobject instance,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
Impl* const impl = GetInstancePtr<Impl>(env, instance);
|
||||||
|
if (!impl) {
|
||||||
|
return ReturnJNIType();
|
||||||
|
}
|
||||||
|
return TypeAdapter<ReturnType>::FromNative(env,
|
||||||
|
(impl->*Method)(TypeAdapter<Args>::ToNative(env, args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance method with instance reference
|
||||||
|
template<ReturnType (Impl::*Method) (typename Owner::Param, Args...)>
|
||||||
|
static ReturnJNIType Wrap(JNIEnv* env, jobject instance,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
Impl* const impl = GetInstancePtr<Impl>(env, instance);
|
||||||
|
if (!impl) {
|
||||||
|
return ReturnJNIType();
|
||||||
|
}
|
||||||
|
return TypeAdapter<ReturnType>::FromNative(env,
|
||||||
|
(impl->*Method)(Owner::Ref::From(instance),
|
||||||
|
TypeAdapter<Args>::ToNative(env, args)...));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for instance methods with void return type
|
||||||
|
template<class Traits, class Impl, typename... Args>
|
||||||
|
class NativeStubImpl<false, void, Traits, Impl, jni::Args<Args...>>
|
||||||
|
{
|
||||||
|
typedef typename Traits::Owner Owner;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Instance method
|
||||||
|
template<void (Impl::*Method) (Args...)>
|
||||||
|
static void Wrap(JNIEnv* env, jobject instance,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
Impl* const impl = GetInstancePtr<Impl>(env, instance);
|
||||||
|
if (!impl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(impl->*Method)(TypeAdapter<Args>::ToNative(env, args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance method with instance reference
|
||||||
|
template<void (Impl::*Method) (typename Owner::Param, Args...)>
|
||||||
|
static void Wrap(JNIEnv* env, jobject instance,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
Impl* const impl = GetInstancePtr<Impl>(env, instance);
|
||||||
|
if (!impl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(impl->*Method)(Owner::Ref::From(instance),
|
||||||
|
TypeAdapter<Args>::ToNative(env, args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for static methods with non-void return type
|
||||||
|
template<typename ReturnType, class Traits, class Impl, typename... Args>
|
||||||
|
class NativeStubImpl<true, ReturnType, Traits, Impl, jni::Args<Args...>>
|
||||||
|
{
|
||||||
|
typedef typename TypeAdapter<ReturnType>::JNIType ReturnJNIType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Static method
|
||||||
|
template<ReturnType (*Method) (Args...)>
|
||||||
|
static ReturnJNIType Wrap(JNIEnv* env, jclass,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
return TypeAdapter<ReturnType>::FromNative(env,
|
||||||
|
(*Method)(TypeAdapter<Args>::ToNative(env, args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static method with class reference
|
||||||
|
template<ReturnType (*Method) (ClassObject::Param, Args...)>
|
||||||
|
static ReturnJNIType Wrap(JNIEnv* env, jclass cls,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
return TypeAdapter<ReturnType>::FromNative(env,
|
||||||
|
(*Method)(ClassObject::Ref::From(cls),
|
||||||
|
TypeAdapter<Args>::ToNative(env, args)...));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization for static methods with void return type
|
||||||
|
template<class Traits, class Impl, typename... Args>
|
||||||
|
class NativeStubImpl<true, void, Traits, Impl, jni::Args<Args...>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Static method
|
||||||
|
template<void (*Method) (Args...)>
|
||||||
|
static void Wrap(JNIEnv* env, jclass,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
(*Method)(TypeAdapter<Args>::ToNative(env, args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static method with class reference
|
||||||
|
template<void (*Method) (ClassObject::Param, Args...)>
|
||||||
|
static void Wrap(JNIEnv* env, jclass cls,
|
||||||
|
typename TypeAdapter<Args>::JNIType... args)
|
||||||
|
{
|
||||||
|
(*Method)(ClassObject::Ref::From(cls),
|
||||||
|
TypeAdapter<Args>::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<class Traits, class Impl>
|
||||||
|
struct NativeStub : detail::NativeStubImpl<Traits::isStatic,
|
||||||
|
typename Traits::ReturnType,
|
||||||
|
Traits, Impl, typename Traits::Args>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a JNINativeMethod from a native
|
||||||
|
// method's traits class and a wrapped stub.
|
||||||
|
template<class Traits, typename Ret, typename... Args>
|
||||||
|
constexpr JNINativeMethod MakeNativeMethod(Ret (*stub)(JNIEnv*, Args...))
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
Traits::name,
|
||||||
|
Traits::signature,
|
||||||
|
reinterpret_cast<void*>(stub)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class inherited by implementing class.
|
||||||
|
template<class Cls, class Impl>
|
||||||
|
class NativeImpl
|
||||||
|
{
|
||||||
|
typedef typename Cls::template Natives<Impl> Natives;
|
||||||
|
|
||||||
|
static bool sInited;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Init() {
|
||||||
|
if (sInited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JNIEnv* const env = GetJNIForThread();
|
||||||
|
env->RegisterNatives(Accessor::EnsureClassRef<Cls>(env),
|
||||||
|
Natives::methods,
|
||||||
|
sizeof(Natives::methods) / sizeof(JNINativeMethod));
|
||||||
|
sInited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeImpl() {
|
||||||
|
// Initialize on creation if not already initialized.
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define static member.
|
||||||
|
template<class C, class I>
|
||||||
|
bool NativeImpl<C, I>::sInited;
|
||||||
|
|
||||||
|
} // namespace jni
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_jni_Natives_h__
|
@ -44,6 +44,13 @@ enum class ExceptionMode
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Class to hold the native types of a method's arguments.
|
||||||
|
// For example, if a method has signature (ILjava/lang/String;)V,
|
||||||
|
// its arguments class would be jni::Args<int32_t, jni::String::Param>
|
||||||
|
template<typename...>
|
||||||
|
struct Args {};
|
||||||
|
|
||||||
|
|
||||||
// Base class for all JNI binding classes.
|
// Base class for all JNI binding classes.
|
||||||
// Templated so that we have one sClassRef for each class.
|
// Templated so that we have one sClassRef for each class.
|
||||||
template<class Cls>
|
template<class Cls>
|
||||||
|
@ -28,6 +28,8 @@ template<typename T> struct TypeAdapter;
|
|||||||
|
|
||||||
// TypeAdapter<LocalRef<Cls>> applies when jobject is a return value.
|
// TypeAdapter<LocalRef<Cls>> applies when jobject is a return value.
|
||||||
template<class Cls> struct TypeAdapter<LocalRef<Cls>> {
|
template<class Cls> struct TypeAdapter<LocalRef<Cls>> {
|
||||||
|
typedef decltype(Ref<Cls>(nullptr).Get()) JNIType;
|
||||||
|
|
||||||
static constexpr auto Call = &JNIEnv::CallObjectMethodA;
|
static constexpr auto Call = &JNIEnv::CallObjectMethodA;
|
||||||
static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
|
static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
|
||||||
static constexpr auto Get = &JNIEnv::GetObjectField;
|
static constexpr auto Get = &JNIEnv::GetObjectField;
|
||||||
@ -36,6 +38,10 @@ template<class Cls> struct TypeAdapter<LocalRef<Cls>> {
|
|||||||
static LocalRef<Cls> ToNative(JNIEnv* env, jobject instance) {
|
static LocalRef<Cls> ToNative(JNIEnv* env, jobject instance) {
|
||||||
return LocalRef<Cls>::Adopt(env, instance);
|
return LocalRef<Cls>::Adopt(env, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JNIType FromNative(JNIEnv*, LocalRef<Cls>&& instance) {
|
||||||
|
return instance.Forget();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Cls> constexpr jobject
|
template<class Cls> constexpr jobject
|
||||||
@ -50,10 +56,16 @@ template<class Cls> constexpr jobject
|
|||||||
|
|
||||||
// TypeAdapter<Ref<Cls>> applies when jobject is a parameter value.
|
// TypeAdapter<Ref<Cls>> applies when jobject is a parameter value.
|
||||||
template<class Cls> struct TypeAdapter<Ref<Cls>> {
|
template<class Cls> struct TypeAdapter<Ref<Cls>> {
|
||||||
|
typedef decltype(Ref<Cls>(nullptr).Get()) JNIType;
|
||||||
|
|
||||||
static constexpr auto Set = &JNIEnv::SetObjectField;
|
static constexpr auto Set = &JNIEnv::SetObjectField;
|
||||||
static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;
|
static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;
|
||||||
|
|
||||||
static jobject FromNative(JNIEnv*, const Ref<Cls>& instance) {
|
static Ref<Cls> ToNative(JNIEnv* env, jobject instance) {
|
||||||
|
return Ref<Cls>::From(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JNIType FromNative(JNIEnv*, const Ref<Cls>& instance) {
|
||||||
return instance.Get();
|
return instance.Get();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -73,6 +85,8 @@ template<> struct TypeAdapter<Param<String>>
|
|||||||
#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \
|
#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \
|
||||||
\
|
\
|
||||||
template<> struct TypeAdapter<NativeType> { \
|
template<> struct TypeAdapter<NativeType> { \
|
||||||
|
typedef JNIType JNI##Type; \
|
||||||
|
\
|
||||||
static constexpr auto Call = &JNIEnv::Call ## JNIName ## MethodA; \
|
static constexpr auto Call = &JNIEnv::Call ## JNIName ## MethodA; \
|
||||||
static constexpr auto StaticCall = &JNIEnv::CallStatic ## JNIName ## MethodA; \
|
static constexpr auto StaticCall = &JNIEnv::CallStatic ## JNIName ## MethodA; \
|
||||||
static constexpr auto Get = &JNIEnv::Get ## JNIName ## Field; \
|
static constexpr auto Get = &JNIEnv::Get ## JNIName ## Field; \
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
EXPORTS.mozilla.jni += [
|
EXPORTS.mozilla.jni += [
|
||||||
'Accessors.h',
|
'Accessors.h',
|
||||||
|
'Natives.h',
|
||||||
'Refs.h',
|
'Refs.h',
|
||||||
'Types.h',
|
'Types.h',
|
||||||
'Utils.h',
|
'Utils.h',
|
||||||
|
Loading…
Reference in New Issue
Block a user