Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a java string in C++ using JNI

I need to call my java code and then return a String from C++ using JNI.

Basically in C++ I want to use a function like "String getMyString()" to obtain some string from java. How could I obtain this ?

like image 645
rantravee Avatar asked Nov 05 '22 05:11

rantravee


1 Answers

Follow is my wrapper to return std::wstring. Note that it is uses "critical string"

/**
*   Wraps Get/ReleaseStringCritical pairs of unicode java-string
*/
struct jniCriticalString
{
    jniCriticalString(JNIEnv *env, jstring str):
        _env(env),
        _str(str)
    {
        _pstr = _env->GetStringCritical(_str, &_is_copy);
    }
    ~jniCriticalString()
    {
        if( _pstr != NULL )
        {
            _env->ReleaseStringCritical(_str, _pstr);
        }
    }
    /**
    *   True, if wrapped string is valid - e.g. call of GetStringCritical returned valid value
    */
    bool is_valid() const
    {
        return _pstr != NULL;
    }
    /** True when GetStringCritical created copy instead of direct pointer */
    bool is_copy() const
    {
        return _is_copy == JNI_TRUE;
    }
    /** Return unicode NOT NULL TERMINATED! string.*/
    const wchar_t* c_str() const
    {
        return reinterpret_cast<const wchar_t*>( _pstr );
    }
    /** Get the length of internal string */
    jsize length() const
    {
        return _env->GetStringLength(_str);
    }
    std::wstring as_string() const
    {
        return std::wstring(c_str(), length());
    }
    operator std::wstring () const
    {
        return as_string();
    }

private:
    JNIEnv *_env;
    jstring _str;
    jboolean _is_copy;
    const jchar *_pstr;
};

UPDATED

Following code uses string as input parameter:

JAVA code:

private static native void log_message(
   String category, String message, int level);

C++ impl:

JNIEXPORT void JNICALL Java_bla_bla_bla_bla_log_1message
  (JNIEnv *env, jclass, jstring category, jstring message, jint level)
{
    jniCriticalString pCat(env, category);
    if( !pCat.is_valid() )
        return;
    jniCriticalString pMsg(env, message);
    if( !pMsg.is_valid() )
        return;

    std::wstring lCat(pCat.c_str(), pCat.length());
    std::wstring lmessage(pMsg.c_str(), pMsg.length());
    OP::Logging::instance().log_message(lCat, lmessage, (OP::Logging::LogLevel)level);
}

C++ method to return string uses little bit another technique:

Java_bla_bla_bla_getName(
   JNIEnv *env, jclass operationClass, jlong handler )
        {                                                                                                       
            std::wstring retval = ...
            //.. code to resolve std::wstring

            return env->NewString(
                (const jchar*)retval.c_str(), 
                (jsize)retval.length());


        }
like image 151
Dewfy Avatar answered Nov 09 '22 10:11

Dewfy