On 04.06.2015 18:49, Branko Čibej wrote:
> On 04.06.2015 18:42, Atri Sharma wrote:
>> I like proxy objects although I am wondering if that makes copy by value
>> any more expensive (I am not sure about deep copying of non native objects)
> Note that the only data a proxy object contains is the Java reference --
> a pointer by the current JNI definition. What makes copying more
> expensive is the requirement to maintain a Java global reference in each
> copy. For this, you can either use JNI's NewGlobalRef/DeleteGlobalRef,
> or some kind of native reference counting in C++ -- effectively a shared
> pointer to a (wrapped) Java global reference. I have no ides what's
> faster, but I suspect that the letting JNI take care of reference
> handling is the better option.


Something like the attached prototype.

-- Brane

#include <jni.h>
#include <memory>
#include <stdexcept>

class JavaProxyMixin
{
  protected:
    JavaProxyMixin(const JavaProxyMixin& other)
        : m_env(other.m_env),
          m_jthis(makeref(other.m_env, other.m_jthis))
      {}

    ~JavaProxyMixin()
      {
          if (m_jthis)
              m_env->DeleteGlobalRef(m_jthis);
      }

    JavaProxyMixin& operator=(const JavaProxyMixin& other)
      {
          this->~JavaProxyMixin();
          return *new(this) JavaProxyMixin(other);
      }

    explicit JavaProxyMixin(JNIEnv* env, jobject jthis)
        : m_env(env),
          m_jthis(makeref(env, jthis))
      {}

  private:
    jobject makeref(JNIEnv* env, jobject jthis)
      {
          if (!jthis)
              throw std::invalid_argument("null reference");

          jobject jref = env->NewGlobalRef(jthis);
          if (!jref)
              throw std::bad_alloc();
          return jref;
      }

  protected:
    JNIEnv* const m_env;
    jobject const m_jthis;
};


// Example usage
class ObjectWrapper : private JavaProxyMixin
{
  public:
    explicit ObjectWrapper(JNIEnv* env, jobject jthis)
        : JavaProxyMixin(env, jthis)
      {}

    void fooblerize()
      {
          // Note: needs more error handling
          jclass cls = m_env->FindClass("JavaClass");
          jmethodID mid = m_env->GetMethodID(cls, "fooblerize", "()V");
          m_env->CallVoidMethod(m_jthis, mid);
      }
};

Reply via email to