提交 fd672e41 编写于 作者: J Jason Simmons

JNI/Dart: support for more data types

* Conversion of all primitive types, wrapped Java objects, and nulls between Dart and Java
* A way to distinguish float arguments from doubles when calling Java methods
* Construction of a Dart JniClass from a Java class object
上级 fbd8ea0e
......@@ -6,6 +6,12 @@ source_set("jni") {
sources = [
"dart_jni.cc",
"dart_jni.h",
"jni_array.cc",
"jni_array.h",
"jni_class.cc",
"jni_class.h",
"jni_object.cc",
"jni_object.h",
]
deps = [
......
......@@ -4,12 +4,12 @@
#include "sky/engine/bindings/jni/dart_jni.h"
#include <vector>
#include "base/logging.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/strings/string_util.h"
#include "sky/engine/bindings/jni/jni_array.h"
#include "sky/engine/bindings/jni/jni_class.h"
#include "sky/engine/bindings/jni/jni_object.h"
#include "sky/engine/tonic/dart_args.h"
#include "sky/engine/tonic/dart_binding_macros.h"
#include "sky/engine/tonic/dart_converter.h"
......@@ -19,10 +19,6 @@ namespace blink {
using base::android::ScopedJavaLocalRef;
using base::android::ScopedJavaGlobalRef;
#define ENTER_JNI() \
JNIEnv* env = base::android::AttachCurrentThread(); \
base::android::ScopedJavaLocalFrame java_frame(env);
namespace {
DartLibraryNatives* g_natives = nullptr;
......@@ -37,6 +33,41 @@ const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
return g_natives->GetSymbol(native_function);
}
// Data cached for each Dart isolate.
struct DartJniIsolateData : public base::SupportsUserData::Data {
Dart_PersistentHandle jni_object_type;
Dart_PersistentHandle jni_float_type;
};
// Data cached from the Java VM.
struct DartJniJvmData {
ScopedJavaGlobalRef<jobject> class_loader;
ScopedJavaGlobalRef<jclass> class_clazz;
jmethodID class_loader_load_class_method_id;
jmethodID class_get_name_method_id;
};
DartJniJvmData* g_jvm_data = nullptr;
void* UserDataKey() {
// Return a unique key for our per-isolate data.
static int data_key = 0;
return reinterpret_cast<void*>(&data_key);
}
void CreateIsolateData() {
DartState::Current()->SetUserData(UserDataKey(), new DartJniIsolateData());
}
DartJniIsolateData* IsolateData() {
base::SupportsUserData::Data* user_data =
DartState::Current()->GetUserData(UserDataKey());
DCHECK(user_data);
return static_cast<DartJniIsolateData*>(user_data);
}
} // anonymous namespace
// Check if a JNI API has thrown an exception. If so, convert it to a
// Dart exception.
bool CheckJniException(JNIEnv* env, Dart_Handle *exception) {
......@@ -61,20 +92,43 @@ bool CheckDartException(Dart_Handle result, Dart_Handle* exception) {
return true;
}
} // anonymous namespace
DART_NATIVE_CALLBACK_STATIC(JniClass, FromName);
#define FOR_EACH_BINDING(V) \
V(JniArray, GetLength) \
V(JniClass, CallStaticBooleanMethod) \
V(JniClass, CallStaticByteMethod) \
V(JniClass, CallStaticCharMethod) \
V(JniClass, CallStaticDoubleMethod) \
V(JniClass, CallStaticFloatMethod) \
V(JniClass, CallStaticIntMethod) \
V(JniClass, CallStaticLongMethod) \
V(JniClass, CallStaticObjectMethod) \
V(JniClass, CallStaticShortMethod) \
V(JniClass, CallStaticVoidMethod) \
V(JniClass, NewObject) \
V(JniClass, GetFieldId) \
V(JniClass, GetMethodId) \
V(JniClass, GetStaticBooleanField) \
V(JniClass, GetStaticByteField) \
V(JniClass, GetStaticCharField) \
V(JniClass, GetStaticDoubleField) \
V(JniClass, GetStaticFieldId) \
V(JniClass, GetStaticFloatField) \
V(JniClass, GetStaticIntField) \
V(JniClass, GetStaticLongField) \
V(JniClass, GetStaticMethodId) \
V(JniClass, GetStaticObjectField) \
V(JniClass, GetStaticShortField) \
V(JniClass, SetStaticBooleanField) \
V(JniClass, SetStaticByteField) \
V(JniClass, SetStaticCharField) \
V(JniClass, SetStaticDoubleField) \
V(JniClass, SetStaticFloatField) \
V(JniClass, SetStaticIntField) \
V(JniClass, SetStaticLongField) \
V(JniClass, SetStaticObjectField) \
V(JniClass, SetStaticShortField) \
V(JniObject, CallBooleanMethod) \
V(JniObject, CallIntMethod) \
V(JniObject, CallObjectMethod) \
......@@ -98,35 +152,51 @@ void DartJni::InitForGlobal() {
void DartJni::InitForIsolate() {
DCHECK(g_natives);
Dart_Handle jni_library = Dart_LookupLibrary(ToDart("dart:jni"));
DART_CHECK_VALID(jni_library)
DART_CHECK_VALID(Dart_SetNativeResolver(
Dart_LookupLibrary(ToDart("dart:jni")), GetNativeFunction, GetSymbol));
}
jni_library, GetNativeFunction, GetSymbol));
CreateIsolateData();
ScopedJavaGlobalRef<jobject> DartJni::class_loader_;
jmethodID DartJni::class_loader_load_class_method_id_;
jmethodID DartJni::class_get_name_method_id_;
Dart_Handle object_type = Dart_GetType(
jni_library, ToDart("JniObject"), 0, nullptr);
DART_CHECK_VALID(object_type);
IsolateData()->jni_object_type = Dart_NewPersistentHandle(object_type);
DART_CHECK_VALID(IsolateData()->jni_object_type);
Dart_Handle float_type = Dart_GetType(
jni_library, ToDart("JniFloat"), 0, nullptr);
DART_CHECK_VALID(float_type);
IsolateData()->jni_float_type = Dart_NewPersistentHandle(float_type);
DART_CHECK_VALID(IsolateData()->jni_float_type);
}
bool DartJni::InitJni() {
JNIEnv* env = base::android::AttachCurrentThread();
class_loader_.Reset(base::android::GetClassLoader(env));
DCHECK(!g_jvm_data);
g_jvm_data = new DartJniJvmData();
g_jvm_data->class_loader.Reset(base::android::GetClassLoader(env));
ScopedJavaLocalRef<jclass> class_loader_clazz(
env, env->FindClass("java/lang/ClassLoader"));
CHECK(!base::android::ClearException(env));
class_loader_load_class_method_id_ = env->GetMethodID(
g_jvm_data->class_loader_load_class_method_id = env->GetMethodID(
class_loader_clazz.obj(),
"loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
CHECK(!base::android::ClearException(env));
ScopedJavaLocalRef<jclass> class_clazz(
env, env->FindClass("java/lang/Class"));
g_jvm_data->class_clazz.Reset(env, env->FindClass("java/lang/Class"));
CHECK(!base::android::ClearException(env));
class_get_name_method_id_ = env->GetMethodID(
class_clazz.obj(),
g_jvm_data->class_get_name_method_id = env->GetMethodID(
g_jvm_data->class_clazz.obj(),
"getName",
"()Ljava/lang/String;");
CHECK(!base::android::ClearException(env));
......@@ -136,8 +206,8 @@ bool DartJni::InitJni() {
ScopedJavaLocalRef<jclass> DartJni::GetClass(JNIEnv* env, const char* name) {
jobject clazz = env->CallObjectMethod(
class_loader_.obj(),
class_loader_load_class_method_id_,
g_jvm_data->class_loader.obj(),
g_jvm_data->class_loader_load_class_method_id,
base::android::ConvertUTF8ToJavaString(env, name).obj());
return ScopedJavaLocalRef<jclass>(env, static_cast<jclass>(clazz));
......@@ -147,26 +217,29 @@ std::string DartJni::GetObjectClassName(JNIEnv* env, jobject obj) {
jclass clazz = env->GetObjectClass(obj);
DCHECK(clazz);
jstring name = static_cast<jstring>(
env->CallObjectMethod(clazz, class_get_name_method_id_));
env->CallObjectMethod(clazz, g_jvm_data->class_get_name_method_id));
DCHECK(name);
return base::android::ConvertJavaStringToUTF8(env, name);
}
class JniMethodArgs {
public:
void Convert(JNIEnv* env,
const Vector<Dart_Handle>& dart_args,
Dart_Handle* exception);
jvalue* jvalues() { return jvalues_.data(); }
jclass DartJni::class_clazz() {
return g_jvm_data->class_clazz.obj();
}
private:
jvalue DartToJavaValue(JNIEnv* env,
Dart_Handle handle,
Dart_Handle* exception);
Dart_Handle DartJni::jni_object_type() {
Dart_Handle object_type = Dart_HandleFromPersistent(
IsolateData()->jni_object_type);
DCHECK(!Dart_IsError(object_type));
return object_type;
}
std::vector<jvalue> jvalues_;
};
Dart_Handle DartJni::jni_float_type() {
Dart_Handle float_type = Dart_HandleFromPersistent(
IsolateData()->jni_float_type);
DCHECK(!Dart_IsError(float_type));
return float_type;
}
void JniMethodArgs::Convert(JNIEnv* env,
const Vector<Dart_Handle>& dart_args,
......@@ -187,11 +260,20 @@ jvalue JniMethodArgs::DartToJavaValue(JNIEnv* env,
if (Dart_IsBoolean(dart_value)) {
java_value.z = DartConverter<bool>::FromDart(dart_value);
} else if (Dart_IsInteger(dart_value)) {
return java_value;
}
if (Dart_IsInteger(dart_value)) {
java_value.j = DartConverter<jlong>::FromDart(dart_value);
} else if (Dart_IsDouble(dart_value)) {
return java_value;
}
if (Dart_IsDouble(dart_value)) {
java_value.d = DartConverter<jdouble>::FromDart(dart_value);
} else if (Dart_IsString(dart_value)) {
return java_value;
}
if (Dart_IsString(dart_value)) {
intptr_t length;
Dart_Handle result = Dart_StringLength(dart_value, &length);
if (CheckDartException(result, exception)) return java_value;
......@@ -202,387 +284,48 @@ jvalue JniMethodArgs::DartToJavaValue(JNIEnv* env,
java_value.l = env->NewString(string_data.data(), length);
CheckJniException(env, exception);
} else {
*exception = ToDart("Argument has unsupported data type");
}
return java_value;
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniClass);
JniClass::JniClass(JNIEnv* env, jclass clazz)
: clazz_(env, clazz) {
}
JniClass::~JniClass() {
}
PassRefPtr<JniClass> JniClass::FromName(const char* name) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
ScopedJavaLocalRef<jclass> clazz = DartJni::GetClass(env, name);
if (CheckJniException(env, &exception)) goto fail;
return adoptRef(new JniClass(env, clazz.obj()));
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
intptr_t JniClass::GetFieldId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jfieldID id = env->GetFieldID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
intptr_t JniClass::GetStaticFieldId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jfieldID id = env->GetStaticFieldID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
intptr_t JniClass::GetMethodId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jmethodID id = env->GetMethodID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
return java_value;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
intptr_t JniClass::GetStaticMethodId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jmethodID id = env->GetStaticMethodID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
if (Dart_IsNull(dart_value)) {
java_value.l = nullptr;
return java_value;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
jint JniClass::GetStaticIntField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jint result = env->GetStaticIntField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
bool is_object;
Dart_Handle result = Dart_ObjectIsType(
dart_value, DartJni::jni_object_type(), &is_object);
if (CheckDartException(result, exception)) return java_value;
if (is_object) {
JniObject* jni_object = DartConverter<JniObject*>::FromDart(dart_value);
if (jni_object != nullptr) {
java_value.l = jni_object->java_object();
} else {
*exception = ToDart("Invalid JniObject argument");
}
return java_value;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
PassRefPtr<JniObject> JniClass::GetStaticObjectField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
bool is_float;
result = Dart_ObjectIsType(dart_value, DartJni::jni_float_type(), &is_float);
if (CheckDartException(result, exception)) return java_value;
jobject obj = env->GetStaticObjectField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, obj);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
PassRefPtr<JniObject> JniClass::NewObject(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jobject obj = env->NewObjectA(clazz_.obj(), methodId, java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, obj);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
if (is_float) {
Dart_Handle value_handle = Dart_GetField(dart_value, ToDart("value"));
if (CheckDartException(value_handle, exception)) return java_value;
jlong JniClass::CallStaticLongMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jlong result = env->CallStaticLongMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniObject);
JniObject::JniObject(JNIEnv* env, jobject object)
: object_(env, object) {
}
JniObject::~JniObject() {
}
PassRefPtr<JniObject> JniObject::Create(JNIEnv* env, jobject object) {
std::string class_name = DartJni::GetObjectClassName(env, object);
JniObject* result;
if (class_name == "java.lang.String") {
result = new JniString(env, static_cast<jstring>(object));
} else if (base::StartsWith(class_name, "[L", base::CompareCase::SENSITIVE)) {
result = new JniObjectArray(env, static_cast<jobjectArray>(object));
} else {
result = new JniObject(env, object);
}
return adoptRef(result);
}
jint JniObject::GetIntField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jint result = env->GetIntField(java_object(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
PassRefPtr<JniObject> JniObject::CallObjectMethod(
jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jobject result = env->CallObjectMethodA(java_object(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, result);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
bool JniObject::CallBooleanMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jboolean result = env->CallBooleanMethodA(java_object(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result == JNI_TRUE;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return false;
}
jint JniObject::CallIntMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jint result = env->CallIntMethodA(java_object(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniString);
JniString::JniString(JNIEnv* env, jstring object)
: JniObject(env, object) {}
JniString::~JniString() {
}
jstring JniString::java_string() {
return static_cast<jstring>(java_object());
}
String JniString::GetText() {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jsize length = env->GetStringLength(java_string());
if (CheckJniException(env, &exception)) goto fail;
const jchar* chars = env->GetStringChars(java_string(), NULL);
if (CheckJniException(env, &exception)) goto fail;
String result(chars, length);
env->ReleaseStringChars(java_string(), chars);
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return String();
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniArray);
JniArray::JniArray(JNIEnv* env, jarray array)
: JniObject(env, array) {}
JniArray::~JniArray() {
}
jsize JniArray::GetLength() {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jsize result = env->GetArrayLength(java_array<jarray>());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
template<typename JArrayType>
JArrayType JniArray::java_array() const {
return static_cast<JArrayType>(java_object());
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniObjectArray);
JniObjectArray::JniObjectArray(JNIEnv* env, jobjectArray array)
: JniArray(env, array) {}
JniObjectArray::~JniObjectArray() {
}
PassRefPtr<JniObject> JniObjectArray::GetArrayElement(jsize index) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jobject obj = env->GetObjectArrayElement(java_array<jobjectArray>(),
index);
if (CheckJniException(env, &exception)) goto fail;
double double_value;
result = Dart_DoubleValue(value_handle, &double_value);
if (CheckDartException(result, exception)) return java_value;
return JniObject::Create(env, obj);
java_value.f = static_cast<jfloat>(double_value);
return java_value;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
void JniObjectArray::SetArrayElement(jsize index, const JniObject* value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetObjectArrayElement(java_array<jobjectArray>(), index,
value->java_object());
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
*exception = ToDart("Argument has unsupported data type");
return java_value;
}
} // namespace blink
......@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_ENGINE_BINDINGS_OBJC_DART_JNI_H_
#define SKY_ENGINE_BINDINGS_OBJC_DART_JNI_H_
#ifndef SKY_ENGINE_BINDINGS_JNI_DART_JNI_H_
#define SKY_ENGINE_BINDINGS_JNI_DART_JNI_H_
#include <vector>
#include "base/android/jni_android.h"
#include "base/android/jni_utils.h"
......@@ -12,8 +14,15 @@
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefCounted.h"
#define ENTER_JNI() \
JNIEnv* env = base::android::AttachCurrentThread(); \
base::android::ScopedJavaLocalFrame java_frame(env);
namespace blink {
bool CheckJniException(JNIEnv* env, Dart_Handle *exception);
bool CheckDartException(Dart_Handle result, Dart_Handle* exception);
class DartJni {
public:
static void InitForGlobal();
......@@ -25,111 +34,24 @@ class DartJni {
static std::string GetObjectClassName(JNIEnv* env, jobject obj);
private:
static base::android::ScopedJavaGlobalRef<jobject> class_loader_;
static jmethodID class_loader_load_class_method_id_;
static jmethodID class_get_name_method_id_;
};
class JniObject;
// Wrapper that exposes a JNI jclass to Dart
class JniClass : public RefCounted<JniClass>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~JniClass() override;
static PassRefPtr<JniClass> FromName(const char* className);
intptr_t GetFieldId(const char* name, const char* sig);
intptr_t GetStaticFieldId(const char* name, const char* sig);
intptr_t GetMethodId(const char* name, const char* sig);
intptr_t GetStaticMethodId(const char* name, const char* sig);
jint GetStaticIntField(jfieldID fieldId);
PassRefPtr<JniObject> GetStaticObjectField(jfieldID fieldId);
PassRefPtr<JniObject> NewObject(jmethodID methodId,
const Vector<Dart_Handle>& args);
jlong CallStaticLongMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
private:
JniClass(JNIEnv* env, jclass clazz);
base::android::ScopedJavaGlobalRef<jclass> clazz_;
};
// Wrapper that exposes a JNI jobject to Dart
class JniObject : public RefCounted<JniObject>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~JniObject() override;
static PassRefPtr<JniObject> Create(JNIEnv* env, jobject object);
jobject java_object() const { return object_.obj(); }
jint GetIntField(jfieldID fieldId);
PassRefPtr<JniObject> CallObjectMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
bool CallBooleanMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
jint CallIntMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
protected:
JniObject(JNIEnv* env, jobject object);
base::android::ScopedJavaGlobalRef<jobject> object_;
static jclass class_clazz();
static Dart_Handle jni_object_type();
static Dart_Handle jni_float_type();
};
// Wrapper for a JNI string
class JniString : public JniObject {
DEFINE_WRAPPERTYPEINFO();
friend class JniObject;
class JniMethodArgs {
public:
~JniString() override;
String GetText();
void Convert(JNIEnv* env,
const Vector<Dart_Handle>& dart_args,
Dart_Handle* exception);
jvalue* jvalues() { return jvalues_.data(); }
private:
JniString(JNIEnv* env, jstring string);
jstring java_string();
};
// Wrapper for a JNI array
class JniArray : public JniObject {
DEFINE_WRAPPERTYPEINFO();
jvalue DartToJavaValue(JNIEnv* env,
Dart_Handle handle,
Dart_Handle* exception);
public:
~JniArray() override;
jsize GetLength();
protected:
JniArray(JNIEnv* env, jarray array);
template <typename JArrayType> JArrayType java_array() const;
};
class JniObjectArray : public JniArray {
DEFINE_WRAPPERTYPEINFO();
friend class JniObject;
public:
~JniObjectArray() override;
PassRefPtr<JniObject> GetArrayElement(jsize index);
void SetArrayElement(jsize index, const JniObject* value);
private:
JniObjectArray(JNIEnv* env, jobjectArray array);
std::vector<jvalue> jvalues_;
};
template <>
......@@ -160,4 +82,4 @@ struct DartConverter<jmethodID> {
} // namespace blink
#endif // SKY_ENGINE_BINDINGS_OBJC_DART_JNI_H_
#endif // SKY_ENGINE_BINDINGS_JNI_DART_JNI_H_
......@@ -9,28 +9,94 @@ import 'dart:nativewrappers';
/// Wrapper for a Java class accessed via JNI.
class JniClass extends NativeFieldWrapperClass2 {
static JniClass fromName(String name) native 'JniClass_FromName';
static JniClass fromName(String name)
native 'JniClass_FromName';
static JniClass fromClassObject(JniObject classObject)
native 'JniClass_FromClassObject';
int getFieldId(String name, String sig) native 'JniClass_GetFieldId';
int getStaticFieldId(String name, String sig) native 'JniClass_GetStaticFieldId';
int getMethodId(String name, String sig) native 'JniClass_GetMethodId';
int getStaticMethodId(String name, String sig) native 'JniClass_GetStaticMethodId';
int getFieldId(String name, String sig)
native 'JniClass_GetFieldId';
int getStaticFieldId(String name, String sig)
native 'JniClass_GetStaticFieldId';
int getMethodId(String name, String sig)
native 'JniClass_GetMethodId';
int getStaticMethodId(String name, String sig)
native 'JniClass_GetStaticMethodId';
int getStaticIntField(int fieldId) native 'JniClass_GetStaticIntField';
JniObject getStaticObjectField(int fieldId) native 'JniClass_GetStaticObjectField';
JniObject newObject(int methodId, List args)
native 'JniClass_NewObject';
JniObject newObject(int methodId, List args) native 'JniClass_NewObject';
JniObject getStaticObjectField(int fieldId)
native 'JniClass_GetStaticObjectField';
bool getStaticBooleanField(int fieldId)
native 'JniClass_GetStaticBooleanField';
int getStaticByteField(int fieldId)
native 'JniClass_GetStaticByteField';
int getStaticCharField(int fieldId)
native 'JniClass_GetStaticCharField';
int getStaticShortField(int fieldId)
native 'JniClass_GetStaticShortField';
int getStaticIntField(int fieldId)
native 'JniClass_GetStaticIntField';
int getStaticLongField(int fieldId)
native 'JniClass_GetStaticLongField';
double getStaticFloatField(int fieldId)
native 'JniClass_GetStaticFloatField';
double getStaticDoubleField(int fieldId)
native 'JniClass_GetStaticDoubleField';
int callStaticLongMethod(int methodId, List args) native 'JniClass_CallStaticLongMethod';
void setStaticObjectField(int fieldId, JniObject value)
native 'JniClass_SetStaticObjectField';
void setStaticBooleanField(int fieldId, bool value)
native 'JniClass_SetStaticBooleanField';
void setStaticByteField(int fieldId, int value)
native 'JniClass_SetStaticByteField';
void setStaticCharField(int fieldId, int value)
native 'JniClass_SetStaticCharField';
void setStaticShortField(int fieldId, int value)
native 'JniClass_SetStaticShortField';
void setStaticIntField(int fieldId, int value)
native 'JniClass_SetStaticIntField';
void setStaticLongField(int fieldId, int value)
native 'JniClass_SetStaticLongField';
void setStaticFloatField(int fieldId, double value)
native 'JniClass_SetStaticFloatField';
void setStaticDoubleField(int fieldId, double value)
native 'JniClass_SetStaticDoubleField';
JniObject callStaticObjectMethod(int methodId, List args)
native 'JniClass_CallStaticObjectMethod';
bool callStaticBooleanMethod(int methodId, List args)
native 'JniClass_CallStaticBooleanMethod';
int callStaticByteMethod(int methodId, List args)
native 'JniClass_CallStaticByteMethod';
int callStaticCharMethod(int methodId, List args)
native 'JniClass_CallStaticCharMethod';
int callStaticShortMethod(int methodId, List args)
native 'JniClass_CallStaticShortMethod';
int callStaticIntMethod(int methodId, List args)
native 'JniClass_CallStaticIntMethod';
int callStaticLongMethod(int methodId, List args)
native 'JniClass_CallStaticLongMethod';
double callStaticFloatMethod(int methodId, List args)
native 'JniClass_CallStaticFloatMethod';
double callStaticDoubleMethod(int methodId, List args)
native 'JniClass_CallStaticDoubleMethod';
void callStaticVoidMethod(int methodId, List args)
native 'JniClass_CallStaticVoidMethod';
}
/// Wrapper for a Java object accessed via JNI.
class JniObject extends NativeFieldWrapperClass2 {
int getIntField(String name, String sig) native 'JniObject_getIntField';
int getIntField(int fieldId)
native 'JniObject_GetIntField';
JniObject callObjectMethod(int methodId, List args) native 'JniObject_CallObjectMethod';
bool callBooleanMethod(int methodId, List args) native 'JniObject_CallBooleanMethod';
int callIntMethod(int methodId, List args) native 'JniObject_CallIntMethod';
JniObject callObjectMethod(int methodId, List args)
native 'JniObject_CallObjectMethod';
bool callBooleanMethod(int methodId, List args)
native 'JniObject_CallBooleanMethod';
int callIntMethod(int methodId, List args)
native 'JniObject_CallIntMethod';
}
/// Wrapper for a Java string.
......@@ -49,3 +115,9 @@ class JniObjectArray extends JniArray {
void operator []=(int index, JniObject value) native 'JniObjectArray_SetArrayElement';
}
/// Used to pass arguments of type "float" to Java methods.
class JniFloat {
final double value;
JniFloat(this.value);
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/engine/bindings/jni/jni_array.h"
#include "sky/engine/bindings/jni/dart_jni.h"
namespace blink {
IMPLEMENT_WRAPPERTYPEINFO(jni, JniArray);
JniArray::JniArray(JNIEnv* env, jarray array)
: JniObject(env, array) {}
JniArray::~JniArray() {
}
jsize JniArray::GetLength() {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jsize result = env->GetArrayLength(java_array<jarray>());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
template<typename JArrayType>
JArrayType JniArray::java_array() const {
return static_cast<JArrayType>(java_object());
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniObjectArray);
JniObjectArray::JniObjectArray(JNIEnv* env, jobjectArray array)
: JniArray(env, array) {}
JniObjectArray::~JniObjectArray() {
}
PassRefPtr<JniObject> JniObjectArray::GetArrayElement(jsize index) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jobject obj = env->GetObjectArrayElement(java_array<jobjectArray>(),
index);
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, obj);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
void JniObjectArray::SetArrayElement(jsize index, const JniObject* value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetObjectArrayElement(java_array<jobjectArray>(), index,
value->java_object());
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_ENGINE_BINDINGS_JNI_JNI_ARRAY_H_
#define SKY_ENGINE_BINDINGS_JNI_JNI_ARRAY_H_
#include <jni.h>
#include "sky/engine/bindings/jni/jni_object.h"
namespace blink {
// Wrapper for a JNI array
class JniArray : public JniObject {
DEFINE_WRAPPERTYPEINFO();
public:
~JniArray() override;
jsize GetLength();
protected:
JniArray(JNIEnv* env, jarray array);
template <typename JArrayType> JArrayType java_array() const;
};
class JniObjectArray : public JniArray {
DEFINE_WRAPPERTYPEINFO();
friend class JniObject;
public:
~JniObjectArray() override;
PassRefPtr<JniObject> GetArrayElement(jsize index);
void SetArrayElement(jsize index, const JniObject* value);
private:
JniObjectArray(JNIEnv* env, jobjectArray array);
};
} // namespace blink
#endif // SKY_ENGINE_BINDINGS_JNI_JNI_ARRAY_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/engine/bindings/jni/jni_class.h"
#include "sky/engine/bindings/jni/dart_jni.h"
#include "sky/engine/bindings/jni/jni_object.h"
namespace blink {
using base::android::ScopedJavaLocalRef;
IMPLEMENT_WRAPPERTYPEINFO(jni, JniClass);
JniClass::JniClass(JNIEnv* env, jclass clazz)
: clazz_(env, clazz) {
}
JniClass::~JniClass() {
}
PassRefPtr<JniClass> JniClass::FromName(const char* name) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
ScopedJavaLocalRef<jclass> clazz = DartJni::GetClass(env, name);
if (CheckJniException(env, &exception)) goto fail;
return adoptRef(new JniClass(env, clazz.obj()));
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
PassRefPtr<JniClass> JniClass::FromClassObject(const JniObject* classObject) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jobject class_object = classObject->java_object();
if (!env->IsInstanceOf(class_object, DartJni::class_clazz())) {
exception = ToDart("invalid JNI class object");
goto fail;
}
return adoptRef(new JniClass(env, static_cast<jclass>(class_object)));
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
intptr_t JniClass::GetFieldId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jfieldID id = env->GetFieldID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
intptr_t JniClass::GetStaticFieldId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jfieldID id = env->GetStaticFieldID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
intptr_t JniClass::GetMethodId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jmethodID id = env->GetMethodID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
intptr_t JniClass::GetStaticMethodId(const char* name, const char* sig) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jmethodID id = env->GetStaticMethodID(clazz_.obj(), name, sig);
if (CheckJniException(env, &exception)) goto fail;
return reinterpret_cast<intptr_t>(id);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
PassRefPtr<JniObject> JniClass::NewObject(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jobject obj = env->NewObjectA(clazz_.obj(), methodId, java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, obj);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
PassRefPtr<JniObject> JniClass::GetStaticObjectField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jobject obj = env->GetStaticObjectField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, obj);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
bool JniClass::GetStaticBooleanField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jboolean result = env->GetStaticBooleanField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result == JNI_TRUE;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return false;
}
int64_t JniClass::GetStaticByteField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jbyte result = env->GetStaticByteField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::GetStaticCharField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jchar result = env->GetStaticCharField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::GetStaticShortField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jshort result = env->GetStaticShortField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::GetStaticIntField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jint result = env->GetStaticIntField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::GetStaticLongField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jlong result = env->GetStaticLongField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
double JniClass::GetStaticFloatField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jfloat result = env->GetStaticFloatField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
double JniClass::GetStaticDoubleField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jfloat result = env->GetStaticDoubleField(clazz_.obj(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
void JniClass::SetStaticObjectField(jfieldID fieldId, const JniObject* value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticObjectField(clazz_.obj(), fieldId, value->java_object());
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticBooleanField(jfieldID fieldId, bool value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticBooleanField(clazz_.obj(), fieldId,
value ? JNI_TRUE : JNI_FALSE);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticByteField(jfieldID fieldId, int64_t value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticByteField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticCharField(jfieldID fieldId, int64_t value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticCharField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticShortField(jfieldID fieldId, int64_t value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticShortField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticIntField(jfieldID fieldId, int64_t value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticIntField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticLongField(jfieldID fieldId, int64_t value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticLongField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticFloatField(jfieldID fieldId, double value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticFloatField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
void JniClass::SetStaticDoubleField(jfieldID fieldId, double value) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
env->SetStaticDoubleField(clazz_.obj(), fieldId, value);
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
PassRefPtr<JniObject> JniClass::CallStaticObjectMethod(
jmethodID methodId, const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jobject obj = env->CallStaticObjectMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, obj);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
bool JniClass::CallStaticBooleanMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jboolean result = env->CallStaticBooleanMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result == JNI_TRUE;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return false;
}
int64_t JniClass::CallStaticByteMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jbyte result = env->CallStaticByteMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::CallStaticCharMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jchar result = env->CallStaticCharMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::CallStaticShortMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jshort result = env->CallStaticShortMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::CallStaticIntMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jint result = env->CallStaticIntMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
int64_t JniClass::CallStaticLongMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jlong result = env->CallStaticLongMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
double JniClass::CallStaticFloatMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jfloat result = env->CallStaticFloatMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
double JniClass::CallStaticDoubleMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jdouble result = env->CallStaticDoubleMethodA(clazz_.obj(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
void JniClass::CallStaticVoidMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
env->CallStaticVoidMethodA(clazz_.obj(), methodId, java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return;
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_ENGINE_BINDINGS_JNI_JNI_CLASS_H_
#define SKY_ENGINE_BINDINGS_JNI_JNI_CLASS_H_
#include <jni.h>
#include "base/android/jni_android.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/PassRefPtr.h"
namespace blink {
class JniObject;
// Wrapper that exposes a JNI jclass to Dart
class JniClass : public RefCounted<JniClass>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~JniClass() override;
static PassRefPtr<JniClass> FromName(const char* className);
static PassRefPtr<JniClass> FromClassObject(const JniObject* classObject);
intptr_t GetFieldId(const char* name, const char* sig);
intptr_t GetStaticFieldId(const char* name, const char* sig);
intptr_t GetMethodId(const char* name, const char* sig);
intptr_t GetStaticMethodId(const char* name, const char* sig);
PassRefPtr<JniObject> NewObject(jmethodID methodId,
const Vector<Dart_Handle>& args);
PassRefPtr<JniObject> GetStaticObjectField(jfieldID fieldId);
bool GetStaticBooleanField(jfieldID fieldId);
int64_t GetStaticByteField(jfieldID fieldId);
int64_t GetStaticCharField(jfieldID fieldId);
int64_t GetStaticShortField(jfieldID fieldId);
int64_t GetStaticIntField(jfieldID fieldId);
int64_t GetStaticLongField(jfieldID fieldId);
double GetStaticFloatField(jfieldID fieldId);
double GetStaticDoubleField(jfieldID fieldId);
void SetStaticObjectField(jfieldID fieldId, const JniObject* value);
void SetStaticBooleanField(jfieldID fieldId, bool value);
void SetStaticByteField(jfieldID fieldId, int64_t value);
void SetStaticCharField(jfieldID fieldId, int64_t value);
void SetStaticShortField(jfieldID fieldId, int64_t value);
void SetStaticIntField(jfieldID fieldId, int64_t value);
void SetStaticLongField(jfieldID fieldId, int64_t value);
void SetStaticFloatField(jfieldID fieldId, double value);
void SetStaticDoubleField(jfieldID fieldId, double value);
PassRefPtr<JniObject> CallStaticObjectMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
bool CallStaticBooleanMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
int64_t CallStaticByteMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
int64_t CallStaticCharMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
int64_t CallStaticShortMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
int64_t CallStaticIntMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
int64_t CallStaticLongMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
double CallStaticFloatMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
double CallStaticDoubleMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
void CallStaticVoidMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
private:
JniClass(JNIEnv* env, jclass clazz);
base::android::ScopedJavaGlobalRef<jclass> clazz_;
};
} // namespace blink
#endif // SKY_ENGINE_BINDINGS_JNI_JNI_CLASS_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/engine/bindings/jni/jni_object.h"
#include "base/strings/string_util.h"
#include "sky/engine/bindings/jni/dart_jni.h"
#include "sky/engine/bindings/jni/jni_array.h"
namespace blink {
IMPLEMENT_WRAPPERTYPEINFO(jni, JniObject);
JniObject::JniObject(JNIEnv* env, jobject object)
: object_(env, object) {
}
JniObject::~JniObject() {
}
PassRefPtr<JniObject> JniObject::Create(JNIEnv* env, jobject object) {
if (object == nullptr)
return nullptr;
std::string class_name = DartJni::GetObjectClassName(env, object);
JniObject* result;
if (class_name == "java.lang.String") {
result = new JniString(env, static_cast<jstring>(object));
} else if (base::StartsWith(class_name, "[L", base::CompareCase::SENSITIVE)) {
result = new JniObjectArray(env, static_cast<jobjectArray>(object));
} else {
result = new JniObject(env, object);
}
return adoptRef(result);
}
int64_t JniObject::GetIntField(jfieldID fieldId) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jint result = env->GetIntField(java_object(), fieldId);
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
PassRefPtr<JniObject> JniObject::CallObjectMethod(
jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jobject result = env->CallObjectMethodA(java_object(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return JniObject::Create(env, result);
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return nullptr;
}
bool JniObject::CallBooleanMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jboolean result = env->CallBooleanMethodA(java_object(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result == JNI_TRUE;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return false;
}
int64_t JniObject::CallIntMethod(jmethodID methodId,
const Vector<Dart_Handle>& args) {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
JniMethodArgs java_args;
java_args.Convert(env, args, &exception);
if (exception) goto fail;
jint result = env->CallIntMethodA(java_object(), methodId,
java_args.jvalues());
if (CheckJniException(env, &exception)) goto fail;
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return 0;
}
IMPLEMENT_WRAPPERTYPEINFO(jni, JniString);
JniString::JniString(JNIEnv* env, jstring object)
: JniObject(env, object) {}
JniString::~JniString() {
}
jstring JniString::java_string() {
return static_cast<jstring>(java_object());
}
String JniString::GetText() {
Dart_Handle exception = nullptr;
{
ENTER_JNI();
jsize length = env->GetStringLength(java_string());
if (CheckJniException(env, &exception)) goto fail;
const jchar* chars = env->GetStringChars(java_string(), NULL);
if (CheckJniException(env, &exception)) goto fail;
String result(chars, length);
env->ReleaseStringChars(java_string(), chars);
return result;
}
fail:
Dart_ThrowException(exception);
ASSERT_NOT_REACHED();
return String();
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_ENGINE_BINDINGS_JNI_JNI_OBJECT_H_
#define SKY_ENGINE_BINDINGS_JNI_JNI_OBJECT_H_
#include <jni.h>
#include "base/android/jni_android.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/PassRefPtr.h"
namespace blink {
// Wrapper that exposes a JNI jobject to Dart
class JniObject : public RefCounted<JniObject>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~JniObject() override;
static PassRefPtr<JniObject> Create(JNIEnv* env, jobject object);
jobject java_object() const { return object_.obj(); }
int64_t GetIntField(jfieldID fieldId);
PassRefPtr<JniObject> CallObjectMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
bool CallBooleanMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
int64_t CallIntMethod(jmethodID methodId,
const Vector<Dart_Handle>& args);
protected:
JniObject(JNIEnv* env, jobject object);
base::android::ScopedJavaGlobalRef<jobject> object_;
};
// Wrapper for a JNI string
class JniString : public JniObject {
DEFINE_WRAPPERTYPEINFO();
friend class JniObject;
public:
~JniString() override;
String GetText();
private:
JniString(JNIEnv* env, jstring string);
jstring java_string();
};
} // namespace blink
#endif // SKY_ENGINE_BINDINGS_JNI_JNI_OBJECT_H_
......@@ -118,7 +118,7 @@ Dart_Isolate IsolateCreateCallback(const char* script_uri,
Dart_Isolate isolate = Dart_CreateIsolate(
script_uri, "main", reinterpret_cast<const uint8_t*>(
DART_SYMBOL(kDartIsolateSnapshotBuffer)),
nullptr, nullptr, error);
nullptr, dart_state, error);
CHECK(isolate) << error;
dart_state->SetIsolate(isolate);
CHECK(Dart_IsServiceIsolate(isolate));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册