diff --git a/wrappers/android/mynteye/libmynteye/CMakeLists.txt b/wrappers/android/mynteye/libmynteye/CMakeLists.txt index 31afdd5..4f84689 100644 --- a/wrappers/android/mynteye/libmynteye/CMakeLists.txt +++ b/wrappers/android/mynteye/libmynteye/CMakeLists.txt @@ -8,11 +8,17 @@ cmake_minimum_required(VERSION 3.4.1) get_filename_component(MYNTETE_ROOT "${PROJECT_SOURCE_DIR}/../../../.." ABSOLUTE) message(STATUS "MYNTETE_ROOT: ${MYNTETE_ROOT}") +get_filename_component(PRO_ROOT "${PROJECT_SOURCE_DIR}/.." ABSOLUTE) +message(STATUS "PRO_ROOT: ${PRO_ROOT}") + +set(LIB_ROOT "${PROJECT_SOURCE_DIR}") +message(STATUS "LIB_ROOT: ${LIB_ROOT}") + if(NOT DJINNI_DIR) if(DEFINED ENV{DJINNI_DIR}) set(DJINNI_DIR $ENV{DJINNI_DIR}) else() - set(DJINNI_DIR "$ENV{HOME}/Workspace/Fever/Dropbox/djinni") + set(DJINNI_DIR "${PRO_ROOT}/third_party/djinni") endif() endif() diff --git a/wrappers/android/mynteye/third_party/djinni/support-lib/djinni_common.hpp b/wrappers/android/mynteye/third_party/djinni/support-lib/djinni_common.hpp new file mode 100644 index 0000000..0892a32 --- /dev/null +++ b/wrappers/android/mynteye/third_party/djinni/support-lib/djinni_common.hpp @@ -0,0 +1,33 @@ +// +// Copyright 2015 Dropbox, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#pragma once + +#ifdef _MSC_VER + #define DJINNI_WEAK_DEFINITION // weak attribute not supported by MSVC + #define DJINNI_NORETURN_DEFINITION __declspec(noreturn) + #if _MSC_VER < 1900 // snprintf not implemented prior to VS2015 + #define DJINNI_SNPRINTF snprintf + #define noexcept _NOEXCEPT // work-around for missing noexcept VS2015 + #define constexpr // work-around for missing constexpr VS2015 + #else + #define DJINNI_SNPRINTF _snprintf + #endif +#else + #define DJINNI_WEAK_DEFINITION __attribute__((weak)) + #define DJINNI_NORETURN_DEFINITION __attribute__((noreturn)) + #define DJINNI_SNPRINTF snprintf +#endif diff --git a/wrappers/android/mynteye/third_party/djinni/support-lib/jni/Marshal.hpp b/wrappers/android/mynteye/third_party/djinni/support-lib/jni/Marshal.hpp new file mode 100644 index 0000000..fcced9b --- /dev/null +++ b/wrappers/android/mynteye/third_party/djinni/support-lib/jni/Marshal.hpp @@ -0,0 +1,536 @@ +// +// Copyright 2014 Dropbox, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#pragma once + +#include "djinni_support.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace djinni +{ + template + class Primitive + { + public: + using CppType = CppT; + using JniType = JniT; + + static CppType toCpp(JNIEnv* /*jniEnv*/, JniType j) noexcept { return static_cast(j); } + static JniType fromCpp(JNIEnv* /*jniEnv*/, CppType c) noexcept { return static_cast(c); } + + struct Boxed + { + using JniType = jobject; + static CppType toCpp(JNIEnv* jniEnv, JniType j) + { + assert(j != nullptr); + const auto& data = JniClass::get(); + assert(jniEnv->IsInstanceOf(j, data.clazz.get())); + auto ret = Primitive::toCpp(jniEnv, Self::unbox(jniEnv, data.method_unbox, j)); + jniExceptionCheck(jniEnv); + return ret; + } + static LocalRef fromCpp(JNIEnv* jniEnv, CppType c) + { + const auto& data = JniClass::get(); + auto ret = jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_box, Primitive::fromCpp(jniEnv, c)); + jniExceptionCheck(jniEnv); + return {jniEnv, ret}; + } + }; + + protected: + Primitive(const char* javaClassSpec, + const char* staticBoxMethod, + const char* staticBoxMethodSignature, + const char* unboxMethod, + const char* unboxMethodSignature) + : clazz(jniFindClass(javaClassSpec)) + , method_box(jniGetStaticMethodID(clazz.get(), staticBoxMethod, staticBoxMethodSignature)) + , method_unbox(jniGetMethodID(clazz.get(), unboxMethod, unboxMethodSignature)) + {} + + private: + const GlobalRef clazz; + const jmethodID method_box; + const jmethodID method_unbox; + }; + + class Bool : public Primitive + { + Bool() : Primitive("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", "booleanValue", "()Z") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallBooleanMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + class I8 : public Primitive + { + I8() : Primitive("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", "byteValue", "()B") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallByteMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + class I16 : public Primitive + { + I16() : Primitive("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", "shortValue", "()S") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallShortMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + class I32 : public Primitive + { + I32() : Primitive("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", "intValue", "()I") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallIntMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + class I64 : public Primitive + { + I64() : Primitive("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", "longValue", "()J") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallLongMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + class F32 : public Primitive + { + F32() : Primitive("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", "floatValue", "()F") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallFloatMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + class F64 : public Primitive + { + F64() : Primitive("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", "doubleValue", "()D") {} + friend JniClass; + friend Primitive; + static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) { + auto result = jniEnv->CallDoubleMethod(j, method); + jniExceptionCheck(jniEnv); + return result; + } + }; + + struct String + { + using CppType = std::string; + using JniType = jstring; + + using Boxed = String; + + static CppType toCpp(JNIEnv* jniEnv, JniType j) + { + assert(j != nullptr); + return jniUTF8FromString(jniEnv, j); + } + + static LocalRef fromCpp(JNIEnv* jniEnv, const CppType& c) + { + return {jniEnv, jniStringFromUTF8(jniEnv, c)}; + } + }; + + struct WString + { + using CppType = std::wstring; + using JniType = jstring; + + using Boxed = WString; + + static CppType toCpp(JNIEnv* jniEnv, JniType j) + { + assert(j != nullptr); + return jniWStringFromString(jniEnv, j); + } + + static LocalRef fromCpp(JNIEnv* jniEnv, const CppType& c) + { + return {jniEnv, jniStringFromWString(jniEnv, c)}; + } + }; + + struct Binary + { + using CppType = std::vector; + using JniType = jbyteArray; + + using Boxed = Binary; + + static CppType toCpp(JNIEnv* jniEnv, JniType j) + { + assert(j != nullptr); + + std::vector ret; + jsize length = jniEnv->GetArrayLength(j); + jniExceptionCheck(jniEnv); + + if (!length) { + return ret; + } + + { + auto deleter = [jniEnv, j] (void* c) { + if (c) { + jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT); + } + }; + + std::unique_ptr ptr( + reinterpret_cast(jniEnv->GetPrimitiveArrayCritical(j, nullptr)), + deleter + ); + + if (ptr) { + // Construct and then move-assign. This copies the elements only once, + // and avoids having to initialize before filling (as with resize()) + ret = std::vector{ptr.get(), ptr.get() + length}; + } else { + // Something failed... + jniExceptionCheck(jniEnv); + } + } + + return ret; + } + + static LocalRef fromCpp(JNIEnv* jniEnv, const CppType& c) + { + assert(c.size() <= std::numeric_limits::max()); + auto j = LocalRef(jniEnv, jniEnv->NewByteArray(static_cast(c.size()))); + jniExceptionCheck(jniEnv); + // Using .data() on an empty vector is UB + if(!c.empty()) + { + jniEnv->SetByteArrayRegion(j.get(), 0, jsize(c.size()), reinterpret_cast(c.data())); + } + return j; + } + }; + + struct Date + { + using CppType = std::chrono::system_clock::time_point; + using JniType = jobject; + + using Boxed = Date; + + static CppType toCpp(JNIEnv* jniEnv, JniType j) + { + static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0); + assert(j != nullptr); + const auto & data = JniClass::get(); + assert(jniEnv->IsInstanceOf(j, data.clazz.get())); + auto time_millis = jniEnv->CallLongMethod(j, data.method_get_time); + jniExceptionCheck(jniEnv); + return POSIX_EPOCH + std::chrono::milliseconds{time_millis}; + } + + static LocalRef fromCpp(JNIEnv* jniEnv, const CppType& c) + { + static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0); + const auto & data = JniClass::get(); + const auto cpp_millis = std::chrono::duration_cast(c - POSIX_EPOCH); + const jlong millis = static_cast(cpp_millis.count()); + auto j = LocalRef(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, millis)); + jniExceptionCheck(jniEnv); + return j; + } + + private: + Date() = default; + friend ::djinni::JniClass; + + const GlobalRef clazz { jniFindClass("java/util/Date") }; + const jmethodID constructor { jniGetMethodID(clazz.get(), "", "(J)V") }; + const jmethodID method_get_time { jniGetMethodID(clazz.get(), "getTime", "()J") }; + }; + + template