// This file was generated by
//     //third_party/jni_zero/jni_zero.py
// For
//     org.jni_zero.SampleForTests

#ifndef org_jni_zero_SampleForTests_JNI
#define org_jni_zero_SampleForTests_JNI

#include <jni.h>

#include "third_party/jni_zero/jni_export.h"
#include "third_party/jni_zero/jni_zero_helper.h"
// Class Accessors.
#ifndef org_jni_1zero_SampleForTests_clazz_defined
#define org_jni_1zero_SampleForTests_clazz_defined
inline jclass org_jni_1zero_SampleForTests_clazz(JNIEnv* env) {
  static const char kClassName[] = "org/jni_zero/SampleForTests";
  static std::atomic<jclass> cached_class;
  return jni_zero::internal::LazyGetClass(env, kClassName, &cached_class);
}
#endif

#ifndef org_jni_1zero_SampleForTests_00024InnerStructA_clazz_defined
#define org_jni_1zero_SampleForTests_00024InnerStructA_clazz_defined
inline jclass org_jni_1zero_SampleForTests_00024InnerStructA_clazz(JNIEnv* env) {
  static const char kClassName[] = "org/jni_zero/SampleForTests$InnerStructA";
  static std::atomic<jclass> cached_class;
  return jni_zero::internal::LazyGetClass(env, kClassName, &cached_class);
}
#endif

#ifndef org_jni_1zero_SampleForTests_00024InnerStructB_clazz_defined
#define org_jni_1zero_SampleForTests_00024InnerStructB_clazz_defined
inline jclass org_jni_1zero_SampleForTests_00024InnerStructB_clazz(JNIEnv* env) {
  static const char kClassName[] = "org/jni_zero/SampleForTests$InnerStructB";
  static std::atomic<jclass> cached_class;
  return jni_zero::internal::LazyGetClass(env, kClassName, &cached_class);
}
#endif

// Forward declare used conversion functions to avoid a compiler warning that
// triggers if a conversion specialization exists within the including .cc file.
namespace jni_zero {
template<> jni_zero::ScopedJavaLocalRef<jstring> ToJniType<const char*, jstring>(JNIEnv*, const char* const&);
template<> jni_zero::tests::CPPClass* FromJniType<jni_zero::tests::CPPClass*, jobject>(JNIEnv*, const JavaRef<jobject>&);
template<> std::string FromJniType<std::string, jstring>(JNIEnv*, const JavaRef<jstring>&);
}  // namespace jni_zero
namespace jni_zero {
namespace tests {
// Java to native functions
JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1addStructB(
    JNIEnv* env,
    jclass jcaller,
    jlong nativeCPPClass,
    jobject caller,
    jobject b) {
  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
  CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB")
  native->AddStructB(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller),
      jni_zero::JavaParamRef<jobject>(env, b));
}

JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1destroy(
    JNIEnv* env,
    jclass jcaller,
    jlong nativeCPPClass,
    jobject caller,
    jbyteArray bytes) {
  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
  CHECK_NATIVE_PTR(env, jcaller, native, "Destroy")
  std::vector<uint8_t> bytes_converted = jni_zero::ConvertArray<std::vector<uint8_t>>::FromJniType(
      env,
      jni_zero::JavaParamRef<jbyteArray>(env, bytes));
  native->Destroy(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller),
      bytes_converted);
}

// Forward declaration. To be implemented by the including .cc file.
static jni_zero::ScopedJavaLocalRef<jclass> JNI_SampleForTests_GetClass(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jclass>& arg0);

JNI_BOUNDARY_EXPORT jclass Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getClass(
    JNIEnv* env,
    jclass jcaller,
    jclass arg0) {
  auto ret = JNI_SampleForTests_GetClass(
      env,
      jni_zero::JavaParamRef<jclass>(env, arg0));
  return ret.Release();
}

// Forward declaration. To be implemented by the including .cc file.
static jdouble JNI_SampleForTests_GetDoubleFunction(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jobject>& caller);

JNI_BOUNDARY_EXPORT jdouble Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getDoubleFunction(
    JNIEnv* env,
    jclass jcaller,
    jobject caller) {
  auto ret = JNI_SampleForTests_GetDoubleFunction(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller));
  return ret;
}

// Forward declaration. To be implemented by the including .cc file.
static jfloat JNI_SampleForTests_GetFloatFunction(JNIEnv* env);

JNI_BOUNDARY_EXPORT jfloat Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getFloatFunction(
    JNIEnv* env,
    jclass jcaller) {
  auto ret = JNI_SampleForTests_GetFloatFunction(env);
  return ret;
}

// Forward declaration. To be implemented by the including .cc file.
static jni_zero::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetMap(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jobject>& arg0);

JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getMap(
    JNIEnv* env,
    jclass jcaller,
    jobject arg0) {
  auto ret = JNI_SampleForTests_GetMap(
      env,
      jni_zero::JavaParamRef<jobject>(env, arg0));
  return ret.Release();
}

// Forward declaration. To be implemented by the including .cc file.
static jni_zero::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jobject>& caller);

JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getNonPODDatatype(
    JNIEnv* env,
    jclass jcaller,
    jobject caller) {
  auto ret = JNI_SampleForTests_GetNonPODDatatype(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller));
  return ret.Release();
}

// Forward declaration. To be implemented by the including .cc file.
static jni_zero::ScopedJavaLocalRef<jthrowable> JNI_SampleForTests_GetThrowable(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jthrowable>& arg0);

JNI_BOUNDARY_EXPORT jthrowable Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getThrowable(
    JNIEnv* env,
    jclass jcaller,
    jthrowable arg0) {
  auto ret = JNI_SampleForTests_GetThrowable(
      env,
      jni_zero::JavaParamRef<jthrowable>(env, arg0));
  return ret.Release();
}

// Forward declaration. To be implemented by the including .cc file.
static jlong JNI_SampleForTests_Init(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jobject>& caller,
    const jni_zero::JavaParamRef<jstring>& param,
    jni_zero::ByteArrayView& bytes,
    jni_zero::tests::CPPClass* convertedType);

JNI_BOUNDARY_EXPORT jlong Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1init(
    JNIEnv* env,
    jclass jcaller,
    jobject caller,
    jstring param,
    jbyteArray bytes,
    jobject convertedType) {
  jni_zero::ByteArrayView bytes_converted = jni_zero::ConvertArray<jni_zero::ByteArrayView>::FromJniType(
      env,
      jni_zero::JavaParamRef<jbyteArray>(env, bytes));
  jni_zero::tests::CPPClass* convertedType_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass*, jobject>(
      env,
      jni_zero::JavaParamRef<jobject>(env, convertedType));
  auto ret = JNI_SampleForTests_Init(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller),
      jni_zero::JavaParamRef<jstring>(env, param),
      bytes_converted,
      convertedType_converted);
  return ret;
}

JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1iterateAndDoSomethingWithStructB(
    JNIEnv* env,
    jclass jcaller,
    jlong nativeCPPClass,
    jobject caller) {
  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
  CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB")
  native->IterateAndDoSomethingWithStructB(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller));
}

JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1method(
    JNIEnv* env,
    jclass jcaller,
    jlong nativeCPPClass,
    jobject caller,
    jobjectArray strings) {
  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
  CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0)
  std::vector<std::string> strings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType<jstring>(
      env,
      jni_zero::JavaParamRef<jobjectArray>(env, strings));
  auto ret = native->Method(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller),
      strings_converted);
  return ret;
}

JNI_BOUNDARY_EXPORT jdouble Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1methodOtherP0(
    JNIEnv* env,
    jclass jcaller,
    jlong nativePtr,
    jobject caller) {
  CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr);
  CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0)
  auto ret = native->MethodOtherP0(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller));
  return ret;
}

JNI_BOUNDARY_EXPORT jstring Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1returnAString(
    JNIEnv* env,
    jclass jcaller,
    jlong nativeCPPClass,
    jobject caller) {
  CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
  CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", nullptr)
  auto ret = native->ReturnAString(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller));
  return ret.Release();
}

// Forward declaration. To be implemented by the including .cc file.
static void JNI_SampleForTests_SetNonPODDatatype(
    JNIEnv* env,
    const jni_zero::JavaParamRef<jobject>& caller,
    const jni_zero::JavaParamRef<jobject>& rect);

JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1setNonPODDatatype(
    JNIEnv* env,
    jclass jcaller,
    jobject caller,
    jobject rect) {
  JNI_SampleForTests_SetNonPODDatatype(
      env,
      jni_zero::JavaParamRef<jobject>(env, caller),
      jni_zero::JavaParamRef<jobject>(env, rect));
}

// Native to Java functions
static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_Constructor(
    JNIEnv* env,
    JniIntWrapper foo,
    JniIntWrapper bar) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "<init>",
      "(II)V",
      &cached_method_id);
  auto ret = env->NewObject(
      clazz,
      call_context.method_id(),
      as_jint(foo),
      as_jint(bar));
  return jni_zero::ScopedJavaLocalRef<jobject>(env, ret);
}

static void Java_SampleForTests_addStructA(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    const jni_zero::JavaRef<jobject>& a) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "addStructA",
      "(Lorg/jni_zero/SampleForTests$InnerStructA;)V",
      &cached_method_id);
  env->CallVoidMethod(obj.obj(), call_context.method_id(), a.obj());
}

static jni_zero::ScopedJavaLocalRef<jclass> Java_SampleForTests_getClass(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    const jni_zero::JavaRef<jclass>& arg0) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "getClass",
      "(Ljava/lang/Class;)Ljava/lang/Class;",
      &cached_method_id);
  auto ret = env->CallObjectMethod(
      obj.obj(),
      call_context.method_id(),
      arg0.obj());
  jclass ret2 = static_cast<jclass>(ret);
  return jni_zero::ScopedJavaLocalRef<jclass>(env, ret2);
}

static std::string Java_SampleForTests_getFirstString(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    std::vector<const char*> const& array,
    const char* const& finalArg) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "getFirstString",
      "([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
      &cached_method_id);
  jni_zero::ScopedJavaLocalRef<jobjectArray> array_converted = jni_zero::ConvertArray<std::vector<const char*>>::ToJniType<jstring>(
      env,
      array,
      jni_zero::g_string_class);
  jni_zero::ScopedJavaLocalRef<jstring> finalArg_converted = jni_zero::ToJniType<const char*, jstring>(
      env,
      finalArg);
  auto ret = env->CallObjectMethod(
      obj.obj(),
      call_context.method_id(),
      array_converted.obj(),
      finalArg_converted.obj());
  jstring ret2 = static_cast<jstring>(ret);
  return jni_zero::FromJniType<std::string, jstring>(
      env,
      jni_zero::JavaParamRef<jstring>(env, ret2));
}

static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum(
    JNIEnv* env) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_STATIC>(
      env,
      clazz,
      "getInnerEnum",
      "()Lorg/jni_zero/SampleForTests$InnerEnum;",
      &cached_method_id);
  auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id());
  return jni_zero::ScopedJavaLocalRef<jobject>(env, ret);
}

static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum(
    JNIEnv* env,
    JniIntWrapper a) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_STATIC>(
      env,
      clazz,
      "getInnerEnum",
      "(I)Lorg/jni_zero/SampleForTests$InnerEnum;",
      &cached_method_id);
  auto ret = env->CallStaticObjectMethod(
      clazz,
      call_context.method_id(),
      as_jint(a));
  return jni_zero::ScopedJavaLocalRef<jobject>(env, ret);
}

static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerInterface(
    JNIEnv* env) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_STATIC>(
      env,
      clazz,
      "getInnerInterface",
      "()Lorg/jni_zero/SampleForTests$InnerInterface;",
      &cached_method_id);
  auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id());
  return jni_zero::ScopedJavaLocalRef<jobject>(env, ret);
}

static jni_zero::ScopedJavaLocalRef<jthrowable> Java_SampleForTests_getThrowable(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    const jni_zero::JavaRef<jthrowable>& arg0) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "getThrowable",
      "(Ljava/lang/Throwable;)Ljava/lang/Throwable;",
      &cached_method_id);
  auto ret = env->CallObjectMethod(
      obj.obj(),
      call_context.method_id(),
      arg0.obj());
  jthrowable ret2 = static_cast<jthrowable>(ret);
  return jni_zero::ScopedJavaLocalRef<jthrowable>(env, ret2);
}

static void Java_SampleForTests_iterateAndDoSomething(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "iterateAndDoSomething",
      "()V",
      &cached_method_id);
  env->CallVoidMethod(obj.obj(), call_context.method_id());
}

static jint Java_SampleForTests_javaMethod(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    JniIntWrapper foo,
    JniIntWrapper bar) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, 0);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "javaMethod",
      "(II)I",
      &cached_method_id);
  auto ret = env->CallIntMethod(
      obj.obj(),
      call_context.method_id(),
      as_jint(foo),
      as_jint(bar));
  return ret;
}

static void Java_SampleForTests_javaMethodWithAnnotatedParam(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    MyEnum foo,
    JniIntWrapper bar,
    JniIntWrapper baz,
    long bat) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "javaMethodWithAnnotatedParam",
      "(IIIJ)V",
      &cached_method_id);
  jint foo_converted = static_cast<jint>(foo);
  jlong bat_converted = static_cast<jlong>(bat);
  env->CallVoidMethod(
      obj.obj(),
      call_context.method_id(),
      foo_converted,
      as_jint(bar),
      as_jint(baz),
      bat_converted);
}

static void Java_SampleForTests_methodThatThrowsException(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz);
  jni_zero::internal::JniJavaCallContext<false> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "methodThatThrowsException",
      "()V",
      &cached_method_id);
  env->CallVoidMethod(obj.obj(), call_context.method_id());
}

static jboolean Java_SampleForTests_methodWithAnnotationParamAssignment(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, false);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "methodWithAnnotationParamAssignment",
      "()Z",
      &cached_method_id);
  auto ret = env->CallBooleanMethod(obj.obj(), call_context.method_id());
  return ret;
}

static void Java_SampleForTests_methodWithGenericParams(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj,
    const jni_zero::JavaRef<jobject>& foo,
    const jni_zero::JavaRef<jobject>& bar) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "methodWithGenericParams",
      "(Ljava/util/Map;Ljava/util/LinkedList;)V",
      &cached_method_id);
  env->CallVoidMethod(
      obj.obj(),
      call_context.method_id(),
      foo.obj(),
      bar.obj());
}

static void Java_SampleForTests_packagePrivateJavaMethod(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "packagePrivateJavaMethod",
      "()V",
      &cached_method_id);
  env->CallVoidMethod(obj.obj(), call_context.method_id());
}

static jboolean Java_SampleForTests_staticJavaMethod(JNIEnv* env) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, false);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_STATIC>(
      env,
      clazz,
      "staticJavaMethod",
      "()Z",
      &cached_method_id);
  auto ret = env->CallStaticBooleanMethod(clazz, call_context.method_id());
  return ret;
}

static jni_zero::ScopedJavaLocalRef<jobject> Java_InnerStructA_create(
    JNIEnv* env,
    jlong l,
    JniIntWrapper i,
    const jni_zero::JavaRef<jstring>& s) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_00024InnerStructA_clazz(env);
  CHECK_CLAZZ(env, clazz, clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_STATIC>(
      env,
      clazz,
      "create",
      "(JILjava/lang/String;)Lorg/jni_zero/SampleForTests$InnerStructA;",
      &cached_method_id);
  auto ret = env->CallStaticObjectMethod(
      clazz,
      call_context.method_id(),
      l,
      as_jint(i),
      s.obj());
  return jni_zero::ScopedJavaLocalRef<jobject>(env, ret);
}

static jlong Java_InnerStructB_getKey(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_00024InnerStructB_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, 0);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "getKey",
      "()J",
      &cached_method_id);
  auto ret = env->CallLongMethod(obj.obj(), call_context.method_id());
  return ret;
}

static jni_zero::ScopedJavaLocalRef<jstring> Java_InnerStructB_getValue(
    JNIEnv* env,
    const jni_zero::JavaRef<jobject>& obj) {
  static std::atomic<jmethodID> cached_method_id(nullptr);
  jclass clazz = org_jni_1zero_SampleForTests_00024InnerStructB_clazz(env);
  CHECK_CLAZZ(env, obj.obj(), clazz, nullptr);
  jni_zero::internal::JniJavaCallContext<true> call_context;
  call_context.Init<jni_zero::MethodID::TYPE_INSTANCE>(
      env,
      clazz,
      "getValue",
      "()Ljava/lang/String;",
      &cached_method_id);
  auto ret = env->CallObjectMethod(obj.obj(), call_context.method_id());
  jstring ret2 = static_cast<jstring>(ret);
  return jni_zero::ScopedJavaLocalRef<jstring>(env, ret2);
}


}  // namespace tests
}  // namespace jni_zero
#endif  // org_jni_zero_SampleForTests_JNI
