From fdb5a2791fe97bc7d3dcb6b9c47a2202d69f5855 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 30 Aug 2022 20:39:42 -0700 Subject: [PATCH] [wpiutil] jni_util: Add Mac-friendly MakeJLongArray/JArrayRef (#4383) Mac has jlong == long long and int64_t = long, so the types are incompatible despite being the same size. --- .../src/main/native/include/wpi/jni_util.h | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/wpiutil/src/main/native/include/wpi/jni_util.h b/wpiutil/src/main/native/include/wpi/jni_util.h index 585c1c635d..6042f893a9 100644 --- a/wpiutil/src/main/native/include/wpi/jni_util.h +++ b/wpiutil/src/main/native/include/wpi/jni_util.h @@ -179,7 +179,12 @@ class JStringRef { namespace detail { template -class JArrayRefInner {}; +class JArrayRefInner { + public: + operator span() const { // NOLINT + return static_cast(this)->array(); + } +}; /** * Specialization of JArrayRefBase to provide std::string_view conversion. @@ -198,6 +203,25 @@ class JArrayRefInner { } }; +/** + * Specialization of JArrayRefBase to handle both "long long" and "long" on + * 64-bit systems. + */ +template +class JArrayRefInner { + public: + template >> + operator span() const { // NOLINT + auto arr = static_cast(this)->array(); + if (arr.empty()) { + return {}; + } + return {reinterpret_cast(arr.data()), arr.size()}; + } +}; + /** * Base class for J*ArrayRef and CriticalJ*ArrayRef */ @@ -206,8 +230,6 @@ class JArrayRefBase : public JArrayRefInner, T> { public: explicit operator bool() const { return this->m_elements != nullptr; } - operator span() const { return array(); } // NOLINT - span array() const { if (!this->m_elements) { return {}; @@ -538,12 +560,24 @@ inline jbooleanArray MakeJBooleanArray(JNIEnv* env, span arr) { WPI_JNI_MAKEJARRAY(jboolean, Boolean) WPI_JNI_MAKEJARRAY(jbyte, Byte) WPI_JNI_MAKEJARRAY(jshort, Short) -WPI_JNI_MAKEJARRAY(jlong, Long) WPI_JNI_MAKEJARRAY(jfloat, Float) WPI_JNI_MAKEJARRAY(jdouble, Double) #undef WPI_JNI_MAKEJARRAY +template >> +inline jlongArray MakeJLongArray(JNIEnv* env, const T& arr) { + jlongArray jarr = env->NewLongArray(arr.size()); + if (!jarr) { + return nullptr; + } + env->SetLongArrayRegion(jarr, 0, arr.size(), + reinterpret_cast(arr.data())); + return jarr; +} + /** * Convert an array of std::string into a jarray of jstring. *