Click here to Skip to main content
15,895,142 members
Articles / Programming Languages / Java / Java SE

Example of using Object-Oriented Java Native Interface in C++

Rate me:
Please Sign up or sign in to vote.
3.73/5 (10 votes)
3 Feb 2006CPOL4 min read 78.5K   1.8K   39  
Demonstrates an easy way of creating and embedding Java objects into C++ code, with Object-Oriented JNI.
/******************************************************************
 *  All rights reserved � 2005 Vitaly Shelest (Javain Ltd)
 *
 *  File name:              JArrayHelper.h
 *
 *  Last modification:      20.03.2005
 *
 *  Description:            Java Primitive Array Helper class template
 *
 *  Authors:                Vitaly Shelest
 *
 *****************************************************************/

#pragma once
#include "JTypeDef.h"
#include "JNIEnvHelper.h"

#pragma warning( disable : 4290 )
#pragma warning( disable : 4518 )


// Java Array Helper Template

namespace jni_helpers
{
    template<class TAC, class TAJ> 
    class JArrayHelper: public JObject_t
    {
    public:
        // Constructors
        //

        JArrayHelper() throw(BaseException)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            length = 0;
        }

        JArrayHelper(size_t len, LPCTSTR elemClassName = "java/lang/Object") throw(BaseException)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            length = (ULONG)len;
            jobject tmpobject = (jobject)NewArray((ULONG)len, elemClassName);
            Assign(tmpobject);
            if(tmpobject)
                jni_helpers::JNIEnvHelper::DeleteLocalRef(tmpobject);    
            if(len)
            {
				m_harray = GlobalAlloc(GHND, len*sizeof(TAC));
                if(m_harray != NULL)
                {
					m_array = (TAC*)GlobalLock(m_harray);
					if(m_array != NULL)
						StoreArrayElements();
                }
            }
        }

        JArrayHelper(const long len, LPCTSTR elemClassName = "java/lang/Object") throw(BaseException)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            length = len;
            jobject tmpobject = (jobject)NewArray(len, elemClassName);
            Assign(tmpobject);
            if(tmpobject)
                jni_helpers::JNIEnvHelper::DeleteLocalRef(tmpobject);    
            if(len)
            {
				m_harray = GlobalAlloc(GHND, len*sizeof(TAC));
                if(m_harray != NULL)
                {
					m_array = (TAC*)GlobalLock(m_harray);
					if(m_array != NULL)
						StoreArrayElements();
                }
            }
        }

        JArrayHelper(JArrayHelper& a) throw(BaseException)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            Assign((JObject_t&)a);
            TAJ jerray = (TAJ)JObject_t::operator const jobject();
            length  = (jerray != 0)?jni_helpers::JNIEnvHelper::GetArrayLength(jerray):0;
        }


        JArrayHelper(const JObject_t& o) : JObject_t(o)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            TAJ jerray = (TAJ)JObject_t::operator const jobject();
            length  = (jerray != 0)?jni_helpers::JNIEnvHelper::GetArrayLength(jerray):0;
        }


        JArrayHelper(const TAC* a, const long len, LPCTSTR elemClassName = "java/lang/Object") throw(BaseException)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            length = len;
            jobject tmpobject = (jobject)NewArray(len, elemClassName);
            Assign(tmpobject);
            if(tmpobject)
                jni_helpers::JNIEnvHelper::DeleteLocalRef(tmpobject);    
            if(len)
            {
                //m_array = new TAC[len];
                //if(m_array != NULL)
                //{
                //    memcpy(m_array, a, len * sizeof(TAC));
                //    StoreArrayElements();
                //}
				m_harray = GlobalAlloc(GHND, len*sizeof(TAC));
                if(m_harray != NULL)
                {
					m_array = (TAC*)GlobalLock(m_harray);
					if(m_array != NULL)
					{
                        memcpy(m_array, a, len * sizeof(TAC));
						StoreArrayElements();
					}
                }
            }
        }


        JArrayHelper(const TAJ ja) throw(BaseException)
        {
            jitem = 0;
			m_harray = 0;
            m_array = 0;
            Assign((jobject)ja);
            TAJ jerray = (TAJ)JObject_t::operator const jobject();
            length  = (jerray != 0)?jni_helpers::JNIEnvHelper::GetArrayLength(jerray):0;
        }

        // Assignment operators        
        //

	    JArrayHelper& operator=(const JArrayHelper& ja) throw(BaseException)
        {
            Assign((JObject_t&)ja);
			m_harray = 0;
            m_array = 0;
            return *this;
        }

	    JArrayHelper& operator=(const TAJ ja) throw(BaseException)
        {
            Assign((jobject)ja);
			m_harray = 0;
            m_array = 0;
            jitem = 0;
            return *this;
        }


        // Get/Put functions for array items
        //

        __declspec(property(get=get_item, put=put_item))
        TAC item[];
        void put_item(const unsigned int i, const TAC value) throw(BaseException)
        {
			length = Length();
            if(i >= length || i < 0)
                throw ArrayIndexOutOfBoundsException(i, length);
            SetArrayElement(i, (TAC*)(&value));
        }

        TAC get_item(const unsigned int i)
        {
			length = Length();
            if(i >= length || i < 0)
                throw ArrayIndexOutOfBoundsException(i, length);
            if(JObject_t::operator const jobject())
                return GetArrayElement(i);
            return 0;
        }

        // Extractors
        //
        
        operator TAC*()
        {
            GetArrayElements();
            return const_cast<TAC*>(m_array);
        };
        

        operator const TAJ()
        {
            return const_cast<TAJ>(operator const jobject());
        };
    

    // Low-level helper functions
    //
        TAJ Copy() const
        {
            return 0;
        }

        unsigned int Length()
        {
            TAJ obj = (TAJ)JObject_t::operator const jobject();
            if( obj == 0)
                return 0;
            return JNIEnvHelper::GetArrayLength(obj);
        }

        // Extracts data for an array object 
        // used as a modified function parameter
        
        /*
        void Synchronize() throw(BaseException)
        {
            GetArrayElements();
        }
        */

		void DeleteItem(){}

        // Destructor
        //

        virtual ~JArrayHelper() throw(BaseException)
        {
            //if(m_array)
            //    delete[] m_array;
            if(m_array)
				GlobalUnlock(m_harray);
                //delete[] m_array;
			if(m_harray)
				GlobalFree(m_harray);
            m_harray = NULL;
            m_array = NULL;
			DeleteItem();
            jitem = 0;
        }

        // For functions internal usage
    private:
		HGLOBAL m_harray;
        TAC*    m_array;
        mutable unsigned long length;
        TAC     jitem;
    
        /*
        void UpdateJArray() throw(BaseException)
        {
            StoreArrayElements(m_array);
        }
        */

        void GetArrayElements() throw(BaseException)
        {
            jboolean isCopy;
            TAJ tmpjarray = (TAJ)JObject_t::operator const jobject();
            length  = (tmpjarray != NULL)?JNIEnvHelper::GetArrayLength(tmpjarray):0;
            //if(m_array)
            //    delete[] m_array;
            if(m_array)
				GlobalUnlock(m_harray);
                //delete[] m_array;
			if(m_harray)
				GlobalFree(m_harray);
            m_harray = NULL;
            m_array = NULL;
            if(length)
            {
                TAC* array = GetArrayElements(&isCopy);
                //m_array = new TAC[length];
                //memcpy(m_array, array, sizeof(TAC)*length);
				m_harray = GlobalAlloc(GHND, length*sizeof(TAC));
                if(m_harray != NULL)
                {
					m_array = (TAC*)GlobalLock(m_harray);
					if(m_array != NULL)
		                memcpy(m_array, array, sizeof(TAC)*length);
                }
                ReleaseArrayElements(array);
            }
        }

        void StoreArrayElements() throw(BaseException)
        {
            jboolean isCopy;
            jobject arobj = operator const jobject();
            
            length = (arobj != NULL)?jni_helpers::JNIEnvHelper::GetArrayLength((TAJ)arobj):0;
            if(length && m_array)
            {
                TAC* array = GetArrayElements(&isCopy);
                if(array)
                {
                    memcpy(array, m_array, sizeof(TAC)*length);
                    ReleaseArrayElements(array);
                }
            }
        }

        TAC GetArrayElement(int i) throw(BaseException);

        void SetArrayElement(int i, TAC* value) throw(BaseException);

        TAC* GetArrayElements(jboolean* isCopy) throw(BaseException)
        {
            TAC* result = 0;
            if(operator const jobject())
            {
                result = reinterpret_cast<TAC*>(JNIEnvHelper::GetPrimitiveArrayCritical((TAJ)operator const jobject(), isCopy));
                jni_helpers::JNIEnvHelper::exceptionCheck();
            }
            return result;
        }

        void ReleaseArrayElements(TAC* array) throw(BaseException)
        {
            TAJ arobj = (TAJ)operator const jobject();
            if(arobj && array)
            {
                jni_helpers::JNIEnvHelper::ReleasePrimitiveArrayCritical(arobj, array, NULL);
                jni_helpers::JNIEnvHelper::exceptionCheck();
            }
        }

        TAJ NewArray(long, LPCTSTR) throw(BaseException);
    };
    
    // jboolean type function
    //
    
};


inline void jni_helpers::JArrayHelper<jstring, jobjectArray>::DeleteItem()
{
    if(jitem)
        JNIEnvHelper::DeleteGlobalRef(jitem);
	jitem = 0;
}

//inline jni_helpers::JArrayHelper<jstring, jobjectArray>::~JArrayHelper()
//{
//    if(m_array)
//        delete[] m_array;
//    m_array = NULL;
//	DeleteItem();
//    jitem = 0;
//}

inline void jni_helpers::JArrayHelper<jobject, jobjectArray>::DeleteItem()
{
    if(jitem)
        JNIEnvHelper::DeleteGlobalRef(jitem);
	jitem = 0;
}


//inline jni_helpers::JArrayHelper<jobject, jobjectArray>::~JArrayHelper()
//{
//    if(m_array)
//        delete[] m_array;
//    if(jitem)
//        JNIEnvHelper::DeleteGlobalRef(jitem);
//    m_array = NULL;
//    jitem = 0;
//}

inline jbooleanArray jni_helpers::JArrayHelper<jboolean, jbooleanArray>::NewArray(long len, LPCTSTR)
{
	jbooleanArray result = reinterpret_cast<jbooleanArray>(JNIEnvHelper::NewBooleanArray( len ));
	return result;
};

inline jboolean jni_helpers::JArrayHelper<jboolean, jbooleanArray>::GetArrayElement(int i)
{
	jboolean result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetBooleanArrayRegion((jbooleanArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jboolean, jbooleanArray>::SetArrayElement(int i, jboolean* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetBooleanArrayRegion((jbooleanArray)JObject_t::operator const jobject(), i, 1, value);
}

// jbyte type function
//

inline jbyteArray jni_helpers::JArrayHelper<jbyte, jbyteArray>::NewArray( long len, LPCTSTR)
{
	jbyteArray result = reinterpret_cast<jbyteArray>(JNIEnvHelper::NewByteArray( len ));
	return result;
};


inline jbyte jni_helpers::JArrayHelper<jbyte, jbyteArray>::GetArrayElement(int i)
{
	jbyte result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetByteArrayRegion((jbyteArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jbyte, jbyteArray>::SetArrayElement(int i, jbyte* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetByteArrayRegion((jbyteArray)JObject_t::operator const jobject(), i, 1, value);
}

// jchar type function
//

inline jcharArray jni_helpers::JArrayHelper<jchar, jcharArray>::NewArray(long len, LPCTSTR)
{
	jcharArray result = reinterpret_cast<jcharArray>(JNIEnvHelper::NewCharArray( len ));
	return result;
};

inline jchar jni_helpers::JArrayHelper<jchar, jcharArray>::GetArrayElement(int i)
{
	jchar result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetCharArrayRegion((jcharArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jchar, jcharArray>::SetArrayElement(int i, jchar* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetCharArrayRegion((jcharArray)JObject_t::operator const jobject(), i, 1, value);
}

// jshort type function
//

inline jshortArray jni_helpers::JArrayHelper<jshort, jshortArray>::NewArray(long len, LPCTSTR)
{
	jshortArray result = reinterpret_cast<jshortArray>(JNIEnvHelper::NewShortArray( len ));
	return result;
};

inline jshort jni_helpers::JArrayHelper<jshort, jshortArray>::GetArrayElement(int i)
{
	jshort result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetShortArrayRegion((jshortArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jshort, jshortArray>::SetArrayElement(int i, jshort* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetShortArrayRegion((jshortArray)JObject_t::operator const jobject(), i, 1, value);
}

// jint type function
//

inline jintArray jni_helpers::JArrayHelper<jint, jintArray>::NewArray(long len, LPCTSTR)
{
	jintArray result = reinterpret_cast<jintArray>(JNIEnvHelper::NewIntArray( len ));
	return result;
};

inline jint jni_helpers::JArrayHelper<jint, jintArray>::GetArrayElement(int i)
{
	jint result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetIntArrayRegion((jintArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jint, jintArray>::SetArrayElement(int i, jint* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetIntArrayRegion((jintArray)JObject_t::operator const jobject(), i, 1, value);
}

inline void jni_helpers::JArrayHelper<jobject, jobjectArray>::SetArrayElement(int i, jobject* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetObjectArrayElement((jobjectArray)JObject_t::operator const jobject(), i, *value);
}


inline jobject jni_helpers::JArrayHelper<jobject, jobjectArray>::GetArrayElement(int i)
{
	if(JObject_t::operator const jobject())
		return JNIEnvHelper::GetObjectArrayElement((jobjectArray)JObject_t::operator const jobject(), i);
	return 0;
}


// jlong type function
//

inline jlongArray jni_helpers::JArrayHelper<jlong, jlongArray>::NewArray(long len, LPCTSTR)
{
	jlongArray result = reinterpret_cast<jlongArray>(JNIEnvHelper::NewLongArray( len ));
	return result;
};

inline jlong jni_helpers::JArrayHelper<jlong, jlongArray>::GetArrayElement(int i)
{
	jlong result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetLongArrayRegion((jlongArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jlong, jlongArray>::SetArrayElement(int i, jlong* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetLongArrayRegion((jlongArray)JObject_t::operator const jobject(), i, 1, value);
}

// jfloat type function
//

inline jfloatArray jni_helpers::JArrayHelper<jfloat, jfloatArray>::NewArray(long len, LPCTSTR)
{
	jfloatArray result = reinterpret_cast<jfloatArray>(JNIEnvHelper::NewFloatArray( len ));
	return result;
};

inline jfloat jni_helpers::JArrayHelper<jfloat, jfloatArray>::GetArrayElement(int i)
{
	jfloat result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetFloatArrayRegion((jfloatArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jfloat, jfloatArray>::SetArrayElement(int i, jfloat* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetFloatArrayRegion((jfloatArray)JObject_t::operator const jobject(), i, 1, value);
}

// jdouble type function
//

inline jdoubleArray jni_helpers::JArrayHelper<jdouble, jdoubleArray>::NewArray(long len, LPCTSTR)
{
	jdoubleArray result = reinterpret_cast<jdoubleArray>(JNIEnvHelper::NewDoubleArray( len ));
	return result;
};

inline jdouble jni_helpers::JArrayHelper<jdouble, jdoubleArray>::GetArrayElement(int i)
{
	jdouble result = 0;
	if(JObject_t::operator const jobject())
		JNIEnvHelper::GetDoubleArrayRegion((jdoubleArray)JObject_t::operator const jobject(), i, 1, &result);
	return result;
}

inline void jni_helpers::JArrayHelper<jdouble, jdoubleArray>::SetArrayElement(int i, jdouble* value)
{
	if(JObject_t::operator const jobject())
		JNIEnvHelper::SetDoubleArrayRegion((jdoubleArray)JObject_t::operator const jobject(), i, 1, value);
}


//////////////////////////////////////////////////
// Some specific template function implementations
//////////////////////////////////////////////////

// jstring type functions
//

inline jni_helpers::JArrayHelper<jstring, jobjectArray>& jni_helpers::JArrayHelper<jstring, jobjectArray>::operator=(const jobjectArray ja)
{
    if(jitem)
        JNIEnvHelper::DeleteGlobalRef(jitem);
    Assign((jobject)ja);
	m_harray = 0;
    m_array = 0;
    jitem = 0;
    return *this;
}

inline jstring* jni_helpers::JArrayHelper<jstring, jobjectArray>::GetArrayElements(jboolean* isCopy)
{
    return NULL;
}

inline void jni_helpers::JArrayHelper<jstring, jobjectArray>::ReleaseArrayElements(jstring* array)
{

}

inline void jni_helpers::JArrayHelper<jstring, jobjectArray>::put_item(const unsigned int i, const jstring value)
{
    if(JObject_t::operator const jobject() && i < Length() && value)
    {
        jni_helpers::JNIEnvHelper::SetObjectArrayElement((jobjectArray)JObject_t::operator const jobject(), i, value);
        jni_helpers::JNIEnvHelper::exceptionCheck();
    }
}

inline jstring jni_helpers::JArrayHelper<jstring, jobjectArray>::get_item(const unsigned int i)
{
    if(JObject_t::operator const jobject() && i < Length())
    {
        jobject tmpobject = jni_helpers::JNIEnvHelper::GetObjectArrayElement((jobjectArray)JObject_t::operator const jobject(), i);
        if(jitem)
        {
            jni_helpers::JNIEnvHelper::DeleteGlobalRef(jitem);
            jitem = 0;
        }
        if(tmpobject)
        {
            jitem = (jstring)jni_helpers::JNIEnvHelper::NewGlobalRef(tmpobject);
            jni_helpers::JNIEnvHelper::DeleteLocalRef(tmpobject);
        }
        return jitem;
    }
    return 0;
}

inline jobjectArray jni_helpers::JArrayHelper<jstring, jobjectArray>::NewArray(long length, LPCTSTR)
{
    jclass clazz = reinterpret_cast<jclass> (jni_helpers::JNIEnvHelper::getEnv() -> FindClass("java/lang/String"));
    jobjectArray result = reinterpret_cast<jobjectArray>(jni_helpers::JNIEnvHelper::NewObjectArray( length, clazz, NULL ));
    jni_helpers::JNIEnvHelper::getEnv() -> DeleteLocalRef(clazz);
    jni_helpers::JNIEnvHelper::exceptionCheck();
    return result;
}

// jobject type functions
//

inline jni_helpers::JArrayHelper<jobject, jobjectArray>& jni_helpers::JArrayHelper<jobject, jobjectArray>::operator=(const jobjectArray ja)
{
    if(jitem)
        JNIEnvHelper::DeleteGlobalRef(jitem);
    Assign((jobject)ja);
	m_harray = 0;
    m_array = 0;
    jitem = 0;
    return *this;
}

inline jobject* jni_helpers::JArrayHelper<jobject, jobjectArray>::GetArrayElements(jboolean* isCopy)
{
    return NULL;
}

inline void jni_helpers::JArrayHelper<jobject, jobjectArray>::ReleaseArrayElements(jobject* array)
{

}

inline void jni_helpers::JArrayHelper<jobject, jobjectArray>::put_item(const unsigned int i, const jobject value)
{
    if(JObject_t::operator const jobject() && 
        i < Length() && value)
    {
        jni_helpers::JNIEnvHelper::SetObjectArrayElement((jobjectArray)JObject_t::operator const jobject(), i, value);
        jni_helpers::JNIEnvHelper::exceptionCheck();
    }
}

inline jobject jni_helpers::JArrayHelper<jobject, jobjectArray>::get_item(const unsigned int i)
{
    if(JObject_t::operator const jobject() && i < Length())
    {
        jobject tmpobject = jni_helpers::JNIEnvHelper::GetObjectArrayElement((jobjectArray)JObject_t::operator const jobject(), i);
        if(jitem)
        {
            jni_helpers::JNIEnvHelper::DeleteGlobalRef(jitem);
            jitem = 0;
        }
        if(tmpobject)
        {
            jitem = jni_helpers::JNIEnvHelper::NewGlobalRef(tmpobject);
            jni_helpers::JNIEnvHelper::DeleteLocalRef(tmpobject);
        }
        return (jstring)jitem;
    }
    return 0;
}

inline jobjectArray jni_helpers::JArrayHelper<jobject, jobjectArray>::NewArray(long len, LPCTSTR elemClassName)
{
    jclass clazz = reinterpret_cast<jclass> (jni_helpers::JNIEnvHelper::getEnv() -> FindClass(elemClassName));
    jobjectArray result = reinterpret_cast<jobjectArray>(jni_helpers::JNIEnvHelper::NewObjectArray(len, clazz, NULL));
    jni_helpers::JNIEnvHelper::getEnv() -> DeleteLocalRef(clazz);
    jni_helpers::JNIEnvHelper::exceptionCheck();
    return result;
}



// JArray helper definitions
//

namespace jni_helpers
{
    typedef JArrayHelper< jboolean, jbooleanArray >JBooleanArrayHelper;
    typedef JArrayHelper< jbyte,    jbyteArray    >JByteArrayHelper;
    typedef JArrayHelper< jchar,    jcharArray    >JCharArrayHelper;
    typedef JArrayHelper< jshort,   jshortArray   >JShortArrayHelper;
    typedef JArrayHelper< jint,     jintArray     >JIntArrayHelper;
    typedef JArrayHelper< jlong,    jlongArray    >JLongArrayHelper;
    typedef JArrayHelper< jfloat,   jfloatArray   >JFloatArrayHelper;
    typedef JArrayHelper< jdouble,  jdoubleArray  >JDoubleArrayHelper;
    typedef JArrayHelper< jstring,  jobjectArray  >JStringArrayHelper;
    typedef JArrayHelper< jobject,  jobjectArray  >JObjectArrayHelper;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Javain Ltd
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions