summaryrefslogtreecommitdiffstats
path: root/include/jau/jni
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-05-09 01:24:33 +0200
committerSven Gothel <[email protected]>2022-05-09 01:24:33 +0200
commite5421ff1dfed4d26ac40542252aba0c4bb1094b5 (patch)
tree03da8b62e928b3afc7c22d77cf16d10422770d1e /include/jau/jni
parentf61e1835c9a7e547342393f7a77098b7bfd68d22 (diff)
Use `std::shared_ptr<T>` instead of a `naked pointer` for sane lifcycle, see shared_ptr_ref<>; Drop all unique_ptr<> funcs;
- Store `std::shared_ptr<T>*` in `long nativeInstance` - Introduced `shared_ptr_ref<T>`, managing the `std::shared_ptr<T>*` preserved instances. - All historic TinyB code removed
Diffstat (limited to 'include/jau/jni')
-rw-r--r--include/jau/jni/helper_jni.hpp557
1 files changed, 381 insertions, 176 deletions
diff --git a/include/jau/jni/helper_jni.hpp b/include/jau/jni/helper_jni.hpp
index 5a47ffd..e4c9d04 100644
--- a/include/jau/jni/helper_jni.hpp
+++ b/include/jau/jni/helper_jni.hpp
@@ -1,11 +1,8 @@
/*
* Author: Sven Gothel <[email protected]>
- * Copyright (c) 2020 Gothel Software e.K.
+ * Copyright (c) 2020, 2022 Gothel Software e.K.
* Copyright (c) 2020 ZAFENA AB
*
- * Author: Andrei Vasiliu <[email protected]>
- * Copyright (c) 2016 Intel Corporation.
- *
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -224,53 +221,14 @@ namespace jau {
return static_cast<JavaGlobalObj*>(shref.get())->getClass();
}
};
-
- //
- // C++ JavaUplink <-> java access, assuming it implementats JavaUplink: field "long nativeInstance" and native method 'void checkValidInstance()' etc
- //
-
- template <typename T>
- T *getJavaUplinkObject(JNIEnv *env, jobject obj)
- {
- jlong instance = env->GetLongField(obj, getInstanceField(env, obj));
- T *t = reinterpret_cast<T *>(instance);
- if (t == nullptr) {
- throw jau::RuntimeException("Trying to acquire null NativeObject", E_FILE_LINE);
- }
- t->checkValidInstance();
- return t;
- }
-
- template <typename T>
- T *getJavaUplinkObjectUnchecked(JNIEnv *env, jobject obj)
- {
- jlong instance = env->GetLongField(obj, getInstanceField(env, obj));
- return reinterpret_cast<T *>(instance);
- }
-
- template <typename T>
- void setJavaUplinkObject(JNIEnv *env, jobject obj, T *t)
- {
- if (t == nullptr) {
- throw jau::RuntimeException("Trying to create null NativeObject", E_FILE_LINE);
- }
- jlong instance = reinterpret_cast<jlong>(t);
- env->SetLongField(obj, getInstanceField(env, obj), instance);
- }
+ typedef std::shared_ptr<JavaGlobalObj> JavaGlobalObjRef;
//
// C++ JavaAnon <-> java access, all generic
//
-
- template <typename T>
- T *castInstance(jlong instance)
- {
- T *t = reinterpret_cast<T *>(instance);
- if (t == nullptr) {
- throw jau::RuntimeException("Trying to cast null object", E_FILE_LINE);
- }
- return t;
- }
+ // We prefer using `std::shared_ptr<T>` instead of a `naked pointer`,
+ // this way we automatically preserve the native instance lifecycle while within a JNI method.
+ //
template <typename T>
T *getObjectRef(JNIEnv *env, jobject obj, const char* field_name)
@@ -288,63 +246,399 @@ namespace jau {
java_exception_check_and_throw(env, E_FILE_LINE);
}
+ /**
+ * Returns the cast `shared_ptr<T>` pointer from the java object's `long nativeInstance` field.
+ *
+ * If `throw_on_nullptr` is true, throws an exception if the shared_ptr<T> pointer is nullptr.
+ *
+ * @tparam T
+ * @param instance
+ * @param throw_on_nullptr
+ * @return
+ */
template <typename T>
- T *getInstance(JNIEnv *env, jobject obj)
+ std::shared_ptr<T> * castInstance(jlong instance, const bool throw_on_nullptr=true)
{
- jlong instance = env->GetLongField(obj, getInstanceField(env, obj));
- T *t = reinterpret_cast<T *>(instance);
- if (t == nullptr) {
- throw jau::RuntimeException("Trying to acquire null object", E_FILE_LINE);
+ std::shared_ptr<T> * ref_ptr = reinterpret_cast<std::shared_ptr<T> *>(instance);
+ if( throw_on_nullptr ) {
+ if (nullptr == ref_ptr) {
+ throw jau::RuntimeException("null reference store", E_FILE_LINE);
+ }
}
- return t;
+ return ref_ptr;
}
+ /**
+ * Returns the cast `shared_ptr<T>` pointer from the java object's `long nativeInstance` field.
+ *
+ * If `throw_on_nullptr` is true, throws an exception if either the shared_ptr<T> pointer or
+ * its managed object reference is nullptr.
+ *
+ * @tparam T
+ * @param env
+ * @param obj
+ * @param throw_on_nullptr if true, throws exception if instance reference is nullptr (default). Otherwise not.
+ */
template <typename T>
- T *getInstanceUnchecked(JNIEnv *env, jobject obj)
- {
- jlong instance = env->GetLongField(obj, getInstanceField(env, obj));
- return reinterpret_cast<T *>(instance);
+ std::shared_ptr<T>* getInstance(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true) {
+ const jlong nativeInstance = env->GetLongField(obj, getInstanceField(env, obj));
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ std::shared_ptr<T>* ref_ptr = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
+ if( throw_on_nullptr ) {
+ if (nullptr == ref_ptr) {
+ throw jau::RuntimeException("null reference store", E_FILE_LINE);
+ }
+ if (nullptr == *ref_ptr) {
+ throw jau::RuntimeException("null reference", E_FILE_LINE);
+ }
+ }
+ return ref_ptr;
}
+ /**
+ * Deletes the `std::shared_ptr<T>` storage of the java object if exists first
+ * and writes the given `std::shared_ptr<T>` storage pointer into its `long nativeInstance` field.
+ *
+ * @tparam T
+ * @param env
+ * @param obj
+ * @param t
+ */
template <typename T>
- void setInstance(JNIEnv *env, jobject obj, T *t)
+ void setInstance(JNIEnv *env, jobject obj, const std::shared_ptr<T>& t)
{
- if (t == nullptr) {
- throw jau::RuntimeException("Trying to create null object", E_FILE_LINE);
- }
- jlong instance = reinterpret_cast<jlong>(t);
- env->SetLongField(obj, getInstanceField(env, obj), instance);
+ if (t == nullptr) {
+ throw jau::RuntimeException("Trying to create null object", E_FILE_LINE);
+ }
+ const jlong instance = (jlong) (intptr_t) &t;
+
+ jfieldID instance_field = getInstanceField(env, obj);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ {
+ const jlong nativeInstance = env->GetLongField(obj, instance_field);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ std::shared_ptr<T>* other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
+ if( nullptr != other ) {
+ delete other;
+ }
+ }
+ env->SetLongField(obj, instance_field, instance);
+ java_exception_check_and_throw(env, E_FILE_LINE);
}
- inline void clearInstance(JNIEnv *env, jobject obj) {
- env->SetLongField(obj, getInstanceField(env, obj), 0);
+
+ /**
+ * Deletes the `std::shared_ptr<T>` storage of the java object if exists
+ * and write `nullptr` into its `long nativeInstance` field.
+ *
+ * @tparam T
+ * @param env
+ * @param obj
+ */
+ template <typename T>
+ void clearInstance(JNIEnv *env, jobject obj) {
+ jfieldID instance_field = getInstanceField(env, obj);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ {
+ const jlong nativeInstance = env->GetLongField(obj, instance_field);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ std::shared_ptr<T>* other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
+ if( nullptr != other ) {
+ delete other;
+ }
+ }
+ env->SetLongField(obj, instance_field, 0);
+ java_exception_check_and_throw(env, E_FILE_LINE);
}
+ /**
+ * A `std::shared_ptr<T>` storage instance to be copied from and released into a java object's `long nativeInstance` field.
+ *
+ * An instance holds a shared_ptr<T> storage pointer for a managed object T.
+ *
+ * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
+ *
+ * We prefer using `std::shared_ptr<T>` instead of a `naked pointer`,
+ * this way we automatically preserve the native instance lifecycle while within a JNI method.
+ *
+ * @tparam T the managed object type
+ */
template <typename T>
- jobject generic_clone(JNIEnv *env, jobject obj)
- {
- T *obj_generic = getInstance<T>(env, obj);
- T *copy_generic = obj_generic->clone();
+ class shared_ptr_ref {
+ private:
+ std::shared_ptr<T>* ref_ptr;
- jclass generic_class = search_class(env, *copy_generic);
- jmethodID generic_ctor = search_method(env, generic_class, "<init>", "(J)V", false);
+ void safe_delete() {
+ std::shared_ptr<T>* ref_ptr_ = ref_ptr;
+ ref_ptr = nullptr;
+ delete ref_ptr_;
+ }
- jobject result = env->NewObject(generic_class, generic_ctor, (jlong)copy_generic);
- if (!result)
- {
- throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
- }
+ static jlong get_instance(JNIEnv *env, jobject obj) {
+ if( nullptr != obj ) {
+ const jlong res = env->GetLongField(obj, getInstanceField(env, obj));
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ return res;
+ } else {
+ return 0;
+ }
+ }
+ static jlong get_instance(JNIEnv *env, jobject obj, jfieldID instance_field) {
+ if( nullptr != obj ) {
+ const jlong res = env->GetLongField(obj, instance_field);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ return res;
+ } else {
+ return 0;
+ }
+ }
- return result;
- }
+ public:
+ /** Default constructor, nullptr */
+ shared_ptr_ref() noexcept
+ : ref_ptr( new std::shared_ptr<T>() )
+ { }
+
+ /** Copy constructor */
+ shared_ptr_ref(const shared_ptr_ref& o) noexcept
+ : ref_ptr( new std::shared_ptr<T>( o.shared_ptr() ) )
+ { }
+
+ /** Move constructor. */
+ shared_ptr_ref(shared_ptr_ref&& o) noexcept
+ : ref_ptr( o.ref_ptr )
+ {
+ o.ref_ptr = nullptr;
+ }
+
+ /** Assignment operator. */
+ shared_ptr_ref& operator=(const shared_ptr_ref& o) {
+ if( nullptr != ref_ptr ) {
+ *ref_ptr = o.shared_ptr();
+ } else {
+ ref_ptr = new std::shared_ptr<T>( o.shared_ptr() );
+ }
+ return *this;
+ }
+
+ /** Move assignment operator. */
+ shared_ptr_ref& operator=(shared_ptr_ref&& o) {
+ if( nullptr != ref_ptr ) {
+ safe_delete();
+ }
+ ref_ptr = o.ref_ptr;
+ o.ref_ptr = nullptr;
+ return *this;
+ }
+
+ ~shared_ptr_ref() {
+ if( nullptr != ref_ptr ) {
+ safe_delete();
+ }
+ }
+
+ /** Constructs a new instance, taking ownership of the given T pointer. */
+ shared_ptr_ref(T * ptr) noexcept
+ : ref_ptr( new std::shared_ptr<T>( ptr ) )
+ { }
+
+ /** Constructs a new instance, copying the given std::shared_ptr<T>. */
+ shared_ptr_ref(const std::shared_ptr<T>& ref) noexcept
+ : ref_ptr( new std::shared_ptr<T>( ref ) )
+ { }
+
+ /** Constructs a new instance, moving the given std::shared_ptr<T>. */
+ shared_ptr_ref(std::shared_ptr<T>&& ref) noexcept
+ : ref_ptr( new std::shared_ptr<T>( std::move(ref) ) )
+ { }
+
+ /** Assignment operator. */
+ shared_ptr_ref& operator=(const std::shared_ptr<T>& o) {
+ if( nullptr != ref_ptr ) {
+ *ref_ptr = o;
+ } else {
+ ref_ptr = new std::shared_ptr<T>( o );
+ }
+ return *this;
+ }
+
+ /**
+ * Throws an exception if this instances shared_ptr<T> storage is nullptr.
+ *
+ * The managed object reference may be nullptr.
+ */
+ void null_check1() const {
+ if (nullptr == ref_ptr) {
+ throw jau::RuntimeException("null reference store", E_FILE_LINE);
+ }
+ }
+
+ /**
+ * Throws an exception if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ */
+ void null_check2() const {
+ if (nullptr == ref_ptr) {
+ throw jau::RuntimeException("null reference store", E_FILE_LINE);
+ }
+ if (nullptr == *ref_ptr) {
+ throw jau::RuntimeException("null reference", E_FILE_LINE);
+ }
+ }
+
+ /**
+ * Constructs a new instance, copying the instance from the given java `long nativeInstance` value,
+ * representing a java object's shared_ptr<T> storage
+ *
+ * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
+ *
+ * If `throw_on_nullptr` is true, throws an exception if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ *
+ * @param nativeInstance the jlong representation of another shared_ptr<T> storage
+ * @param throw_on_nullptr if true, throws an exception if either this instances shared_ptr<T> storage or the managed object reference is nullptr.
+ */
+ shared_ptr_ref(jlong nativeInstance, const bool throw_on_nullptr=true)
+ : ref_ptr( new std::shared_ptr<T>() )
+ {
+ std::shared_ptr<T> * other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
+ if( nullptr != other && nullptr != *other ) {
+ *ref_ptr = *other;
+ }
+ if( throw_on_nullptr ) {
+ null_check2(); // exception if nullptr, even if other shared_ptr instance becomes nullptr @ copy-ctor
+ }
+ }
+
+ /**
+ * Constructs a new instance, copying the instance from the java object's `long nativeInstance` field.
+ * representing its shared_ptr<T> storage
+ *
+ * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
+ *
+ * If `throw_on_nullptr` is true, throws an exception if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ *
+ * @param env denoting the JVM
+ * @param obj denoting the java object holding the `long nativeInstance` field, representing its shared_ptr<T> storage. Maybe `nullptr`, see `throw_on_nullptr`.
+ * @param throw_on_nullptr if true, throws an exception if either this instances shared_ptr<T> storage or the managed object reference is nullptr.
+ */
+ shared_ptr_ref(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true)
+ : shared_ptr_ref( get_instance(env, obj), throw_on_nullptr )
+ { }
+
+ /**
+ * Release ownership and returns the shared_ptr<T> storage.
+ *
+ * This instance shall not be used anymore.
+ */
+ std::shared_ptr<T>* release() noexcept {
+ const std::shared_ptr<T>* res = ref_ptr;
+ ref_ptr = nullptr;
+ return res;
+ }
+
+ /**
+ * Release ownership and return the jlong representation of the shared_ptr<T> storage.
+ *
+ * This instance shall not be used anymore.
+ */
+ jlong release_to_jlong() noexcept {
+ const jlong res = (jlong) (intptr_t)ref_ptr;
+ ref_ptr = nullptr;
+ return res;
+ }
+
+ /**
+ * Deletes the `std::shared_ptr<T>` storage of the target java object if exists first
+ * and writes this instance's `std::shared_ptr<T>` storage pointer into its `long nativeInstance` field,
+ * then releases ownership, see release_to_jlong().
+ *
+ * This instance shall not be used anymore.
+ *
+ * Throws an exception if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ *
+ * @param env
+ * @param obj the target java object
+ */
+ void release_into_object(JNIEnv *env, jobject obj) {
+ null_check2();
+ if( nullptr == obj ) {
+ throw jau::RuntimeException("null target object", E_FILE_LINE);
+ }
+ jfieldID instance_field = getInstanceField(env, obj);
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ {
+ std::shared_ptr<T> * other = reinterpret_cast<std::shared_ptr<T> *>( get_instance(env, obj, instance_field) );
+ if( nullptr != other ) {
+ delete other;
+ }
+ }
+ env->SetLongField(obj, instance_field, release_to_jlong());
+ java_exception_check_and_throw(env, E_FILE_LINE);
+ }
+
+ /**
+ * Returns true if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ */
+ bool is_null() const noexcept {
+ return nullptr == ref_ptr || nullptr == *ref_ptr;
+ }
+
+ /**
+ * Provides access to the shared_ptr<T> pointer, l-value of storage.
+ */
+ std::shared_ptr<T>* pointer() noexcept {
+ return ref_ptr;
+ }
+
+ /**
+ * Provides access to const reference of shared_ptr<T>, r-value.
+ *
+ * Throws an exception if this instances shared_ptr<T> storage is nullptr.
+ */
+ const std::shared_ptr<T>& shared_ptr() const {
+ null_check1();
+ return *ref_ptr;
+ }
+
+ /**
+ * Provides access to reference of stored T.
+ *
+ * Throws an exception if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ */
+ T& operator*() {
+ null_check2();
+ return *(ref_ptr->get());
+ }
+
+ /**
+ * Provides access to pointer of stored T.
+ *
+ * Throws an exception if either this instances shared_ptr<T> storage or
+ * the managed object reference is nullptr.
+ */
+ T* operator->() {
+ null_check2();
+ return ref_ptr->get();
+ }
+
+ std::string toString() const noexcept {
+ return "shared_ptr_ref[ ptr "+jau::to_hexstring(ref_ptr)+
+ ", obj "+ ( nullptr != ref_ptr ? jau::to_hexstring(ref_ptr->get()) : "null" ) + "]";
+ }
+ };
//
// C++ <-> java type mapping
//
template <typename T>
- jobject convert_instance_to_jobject(JNIEnv *env, T *elem,
- const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, T*)> ctor)
+ jobject convert_instance_to_jobject(JNIEnv *env, const std::shared_ptr<T>& elem,
+ const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<T>&)> ctor)
{
jclass clazz = search_class(env, T::java_class().c_str());
jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
@@ -361,7 +655,8 @@ namespace jau {
template <typename T>
jobject convert_instance_to_jobject(JNIEnv *env, jclass clazz,
- const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, T*)> ctor, T *elem)
+ const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<T>&)> ctor,
+ const std::shared_ptr<T>& elem)
{
jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
@@ -388,7 +683,7 @@ namespace jau {
}
jau::for_each(array.begin(), array.end(), [&](typename T::value_type & elem){
- std::shared_ptr<JavaAnon> objref = elem->getJavaObject();
+ JavaAnonRef objref = elem->getJavaObject();
if ( nullptr == objref ) {
throw InternalError("JavaUplink element of array has no valid java-object: "+elem->toString(), E_FILE_LINE);
}
@@ -398,69 +693,8 @@ namespace jau {
}
template <typename T, typename U>
- jobject convert_vector_uniqueptr_to_jarraylist(JNIEnv *env, T& array, const char *ctor_prototype)
- {
- unsigned int array_size = array.size();
-
- jmethodID arraylist_add;
- jobject result = get_new_arraylist(env, array_size, &arraylist_add);
-
- if (array_size == 0)
- {
- return result;
- }
-
- jclass clazz = search_class(env, U::java_class().c_str());
- jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
-
- for (unsigned int i = 0; i < array_size; ++i)
- {
- U *elem = array[i].release();
- jobject object = env->NewObject(clazz, clazz_ctor, (jlong)elem);
- if (!object)
- {
- throw jau::InternalError("cannot create instance of class", E_FILE_LINE);
- }
- env->CallBooleanMethod(result, arraylist_add, object);
- java_exception_check_and_throw(env, E_FILE_LINE);
- }
- return result;
- }
-
- template <typename T, typename U>
- jobject convert_vector_uniqueptr_to_jarraylist(JNIEnv *env, T& array,
- const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, U*)> ctor)
- {
- unsigned int array_size = array.size();
-
- jmethodID arraylist_add;
- jobject result = get_new_arraylist(env, array_size, &arraylist_add);
-
- if (array_size == 0)
- {
- return result;
- }
-
- jclass clazz = search_class(env, U::java_class().c_str());
- jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
-
- for (unsigned int i = 0; i < array_size; ++i)
- {
- U *elem = array[i].release();
- jobject object = ctor(env, clazz, clazz_ctor, elem);
- if (!object)
- {
- throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
- }
- env->CallBooleanMethod(result, arraylist_add, object);
- java_exception_check_and_throw(env, E_FILE_LINE);
- }
- return result;
- }
-
- template <typename T, typename U>
jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array,
- const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, U*)> ctor)
+ const char *ctor_prototype, std::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<U>&)> ctor)
{
unsigned int array_size = array.size();
@@ -477,35 +711,7 @@ namespace jau {
for (unsigned int i = 0; i < array_size; ++i)
{
- U *elem = array[i].get();
- jobject object = ctor(env, clazz, clazz_ctor, elem);
- if (!object)
- {
- throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
- }
- env->CallBooleanMethod(result, arraylist_add, object);
- java_exception_check_and_throw(env, E_FILE_LINE);
- }
- return result;
- }
-
- template <typename T, typename U>
- jobject convert_vector_uniqueptr_to_jarraylist(JNIEnv *env, T& array, std::function<jobject(JNIEnv*, U*)> ctor)
- {
- unsigned int array_size = array.size();
-
- jmethodID arraylist_add;
- jobject result = get_new_arraylist(env, array_size, &arraylist_add);
-
- if (array_size == 0)
- {
- return result;
- }
-
- for (unsigned int i = 0; i < array_size; ++i)
- {
- U *elem = array[i].release();
- jobject object = ctor(env, elem);
+ jobject object = ctor(env, clazz, clazz_ctor, array[i] /* const std::shared_ptr<U>& */);
if (!object)
{
throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
@@ -517,7 +723,7 @@ namespace jau {
}
template <typename T, typename U>
- jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array, std::function<jobject(JNIEnv*, U*)> ctor)
+ jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array, std::function<jobject(JNIEnv*, const std::shared_ptr<U>&)> ctor)
{
unsigned int array_size = array.size();
@@ -531,8 +737,7 @@ namespace jau {
for (unsigned int i = 0; i < array_size; ++i)
{
- U *elem = array[i].get();
- jobject object = ctor(env, elem);
+ jobject object = ctor(env, array[i] /* const std::shared_ptr<U>& */);
if (!object)
{
throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);