3

C ++コードからJNIリソースを取得/解放するために推奨されるテンプレートセットまたはライブラリは何ですか?

「悪い」例:

//C++ code
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jstring javaString)
{
    //Get the native string from javaString
    const char *nativeString = env->GetStringUTFChars(javaString, 0);

    //Do something with the nativeString

    //DON'T FORGET THIS LINE!!!
    env->ReleaseStringUTFChars(javaString, nativeString);
}

明らかに、誰もが上記のコードではなく、テンプレートセットを使用しています。

jstringの場合、オブジェクトが「スコープ外」になると、GetStringUTFCharsを呼び出してリソースを取得し、ReleaseStringUTFCharsを呼び出して解放します。

auto_ptrテンプレートに似ていますが、たとえばjstringに対してGetStringUTFChars/ReleaseStringUTFCharsを呼び出すようにJNIに合わせて調整する必要があります。

4

2 に答える 2

8

C ++ 11で使用std::unique_ptrできます。これにより、削除者を自分で設定できます。

#include <memory>
#include <functional>

typedef std::unique_ptr<char const[], std::function<void(char const*)>> jni_string_ptr;
// the "std::function" is needed to store any callable†

extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jstring javaString)
{
    //Get the native string from javaString
    jni_string_ptr nativeString(env->GetStringUTFChars(javaString, 0),
        [=](char const* p) mutable{ env->ReleaseStringUTFChars(javaString, p); });
    // lambda as the deleter
    // mutable needed if "ReleaseStringUTFChars" is a non-const method

    //Do something with the nativeString

    // nativeString automatically calls the passed deleter
}

C ++ 03で立ち往生していて、にアクセスできないstd::unique_ptr場合は、実行可能な代替手段boost::shared_arrayを提供します。

#include <boost/shared_ptr.hpp>

typedef boost::shared_array<char const*> jni_string_ptr;

struct jni_string_deleter{
  jni_string_deleter(JNIEnv* e, jstring js)
    : _env(e), _java_string(js) {}

  void operator()(char const* p) const{
    _env->ReleaseStringUTFChars(_java_string, p);
  }

private:
  JNIEnv* _env;
  jstring _java_string;
};

extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jstring javaString)
{
    //Get the native string from javaString
    jni_string_ptr nativeString(env->GetStringUTFChars(javaString, 0),
        jni_string_deleter(env, javaString));

    //Do something with the nativeString

    // nativeString automatically calls the passed deleter
}

†例のように、ここで特定の型消去型を使用して、次shared_arrayの型消去のオーバーヘッドを回避することもできstd::functionます。

struct jni_string_deleter{
  jni_string_deleter(JNIEnv* e, jstring js)
    : _env(e), _java_string(js) {}

  void operator()(char const* p) const{
    _env->ReleaseStringUTFChars(_java_string, p);
  }

private:
  JNIEnv* _env;
  jstring _java_string;
};

typedef std::unique_ptr<char const[], jni_string_deleter> jni_string_ptr;

// create
jni_string_ptr(env->get_the_chars(), jni_string_deleter(env, javaString));
于 2012-10-22T18:49:22.450 に答える
3

ここでのキーワードはRAIIです:

class jni_string {
public:
    jni_string(JNIEnv *env, jstring javaString)
        : env_(env), javaString_(javaString)
    { nativeString_ = env_->GetStringUTFChars(javaString_, 0); }

    ~jni_string() { env_->ReleaseStringUTFChars(javaString_, nativeString_); }

    operator const char *() const { return nativeString_; }
private:
    jni_string(const jni_string &x);
    jni_string &operator=(const jni_string &x);

    JNIEnv *env_;
    jstring javaString_;
    const char *nativeString_;
};

使用法は次のようになります。

//C++ code
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jstring javaString)
{
    //Get the native string from javaString
    jni_string nativeString(env, javaString);

    //Do something with the nativeString
}
于 2012-10-22T19:52:24.913 に答える