5

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 ?

user207421
  • 305,947
  • 44
  • 307
  • 483
rantravee
  • 7,411
  • 9
  • 35
  • 47
  • 1
    Duplicate of http://stackoverflow.com/questions/4359453/calling-a-java-function-from-c-via-jni-that-returns-a-string – Alex Cohn Mar 20 '14 at 15:48
  • Possible duplicate of [Calling a java function from C++ via JNI that returns a string](https://stackoverflow.com/questions/4359453/calling-a-java-function-from-c-via-jni-that-returns-a-string) – user207421 Jul 07 '19 at 06:43
  • Take a look here: http://jnicookbook.owsiak.org/recipe-No-010/ - also, make sure to convert `std::string` to `char*` - `std::string str = "string"; const char *cstr = str.c_str();` – Oo.oO Aug 06 '19 at 16:13

1 Answers1

2

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());


        }
Dewfy
  • 23,277
  • 13
  • 73
  • 121
  • 1
    Could you show example of how to define and initialize a specific jmethodID for this use, then how to use it to call a java function and then to return the string ? – rantravee Dec 02 '10 at 15:00
  • @rantravee - just added samples – Dewfy Dec 02 '10 at 16:05
  • @StockB method Java_bla_bla_bla_bla_log_1message with param 'category' do what you ask about. the same technique can be used for return value. The signature will be `jstring Java_bla_bla_bla_bla_log_1message` – Dewfy Feb 08 '13 at 18:02