/* * Copyright (C) 2013 Team XBMC * http://xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, see * . * */ /* * Copyright (c) 2011-2012 Dmitry Moskalchuk . * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Dmitry Moskalchuk ''AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Dmitry Moskalchuk OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of Dmitry Moskalchuk. */ #pragma once #define HAVE_INTTYPES_H 1 #include #include #include "jutils.hpp" namespace jni { namespace details { template struct jcast_helper; template <> struct jcast_helper { static std::string cast(jstring const &v); }; template <> struct jcast_helper, jobjectArray> { static std::vector cast(jobjectArray const &v); }; template struct jcast_helper, jobjectArray> { static std::vector cast(jobjectArray const &v); }; template <> struct jcast_helper, jbyteArray> { static std::vector cast(jbyteArray const &v) { JNIEnv *env = xbmc_jnienv(); jsize size = 0; std::vector vec; if(v) { size = env->GetArrayLength(v); vec.reserve(size); jbyte *elements = env->GetByteArrayElements(v, NULL); for (int i = 0; i < size; i++) { vec.emplace_back(static_cast(elements[i])); } env->ReleaseByteArrayElements(v, elements, JNI_ABORT); } return vec; } }; template <> struct jcast_helper, jintArray> { static std::vector cast(jintArray const &v) { JNIEnv *env = xbmc_jnienv(); jsize size = 0; if(v) size = env->GetArrayLength(v); std::vector vec; vec.reserve(size); int *elements = env->GetIntArrayElements(v, NULL); for (int i = 0; i < size; i++) { vec.emplace_back(elements[i]); } env->ReleaseIntArrayElements(v, elements, JNI_ABORT); return vec; } }; template <> struct jcast_helper, jshortArray> { static std::vector cast(jshortArray const &v) { JNIEnv *env = xbmc_jnienv(); jsize size = 0; if(v) size = env->GetArrayLength(v); std::vector vec; vec.reserve(size); jshort *elements = env->GetShortArrayElements(v, NULL); for (int i = 0; i < size; i++) { vec.emplace_back(elements[i]); } env->ReleaseShortArrayElements(v, elements, JNI_ABORT); return vec; } }; template <> struct jcast_helper, jlongArray> { static std::vector cast(jlongArray const &v) { JNIEnv *env = xbmc_jnienv(); jsize size = 0; if(v) size = env->GetArrayLength(v); std::vector vec; vec.reserve(size); int64_t *elements = env->GetLongArrayElements(v, NULL); for (int i = 0; i < size; i++) { vec.emplace_back(elements[i]); } env->ReleaseLongArrayElements(v, elements, JNI_ABORT); return vec; } }; template <> struct jcast_helper, jfloatArray> { static std::vector cast(jfloatArray const &v) { JNIEnv *env = xbmc_jnienv(); jsize size = 0; if(v) size = env->GetArrayLength(v); std::vector vec; vec.reserve(size); float *elements = env->GetFloatArrayElements(v, NULL); for (int i = 0; i < size; i++) { vec.emplace_back(elements[i]); } env->ReleaseFloatArrayElements(v, elements, JNI_ABORT); return vec; } }; template <> struct jcast_helper { static jhstring cast(const std::string &v); }; template <> struct jcast_helper > { static jhbyteArray cast(const std::vector &v); }; template <> struct jcast_helper > { static jhshortArray cast(const std::vector &v); }; template <> struct jcast_helper > { static jhfloatArray cast(const std::vector &v); }; template <> struct jcast_helper > { static jhobjectArray cast(const std::vector &v); }; template <> struct jcast_helper { static std::string cast(jhstring const &v) { return jcast_helper::cast(v.get()); } }; template <> struct jcast_helper, jhobjectArray> { static std::vector cast(jhobjectArray const &v) { return jcast_helper, jobjectArray>::cast(v.get()); } }; template struct jcast_helper, jhobjectArray> { static std::vector cast(jhobjectArray const &v) { return jcast_helper, jobjectArray>::cast(v.get()); } }; template <> struct jcast_helper, jhbyteArray> { static std::vector cast(jhbyteArray const &v) { return jcast_helper, jbyteArray>::cast(v.get()); } }; template <> struct jcast_helper, jhintArray> { static std::vector cast(jhintArray const &v) { return jcast_helper, jintArray>::cast(v.get()); } }; template <> struct jcast_helper, jhshortArray> { static std::vector cast(jhshortArray const &v) { return jcast_helper, jshortArray>::cast(v.get()); } }; template <> struct jcast_helper, jhlongArray> { static std::vector cast(jhlongArray const &v) { return jcast_helper, jlongArray>::cast(v.get()); } }; template <> struct jcast_helper, jhfloatArray> { static std::vector cast(jhfloatArray const &v) { return jcast_helper, jfloatArray>::cast(v.get()); } }; template std::vector jcast_helper, jobjectArray>::cast(jobjectArray const &v) { JNIEnv *env = xbmc_jnienv(); jsize size = 0; if(v) size = env->GetArrayLength(v); std::vector vec; vec.reserve(size); for (int i = 0; i < size; i++) { T element((jhobject)env->GetObjectArrayElement(v, i)); vec.emplace_back(element); } return vec; } } // namespace details template T jcast(U const &v) { return details::jcast_helper::cast(v); } inline jhclass find_class(JNIEnv *env, const char *clsname) { return jhclass((jclass)env->FindClass(clsname)); } inline jhclass find_class(const char *clsname) { return find_class(xbmc_jnienv(), clsname); } inline jhclass get_class(JNIEnv *env, jhobject const &obj) { return jhclass(env->GetObjectClass(obj.get())); } inline jhclass get_class(jhobject const &obj) { return get_class(xbmc_jnienv(), obj); } inline jmethodID get_method_id(JNIEnv *env, jhclass const &cls, const char *name, const char *signature) { return env->GetMethodID(cls.get(), name, signature); } inline jmethodID get_method_id(jhclass const &cls, const char *name, const char *signature) { return get_method_id(xbmc_jnienv(), cls, name, signature); } inline jmethodID get_method_id(JNIEnv *env, jhobject const &obj, const char *name, const char *signature) { return get_method_id(env, get_class(env, obj), name, signature); } template jmethodID get_method_id(jholder const &obj, const char *name, const char *signature) { return get_method_id(xbmc_jnienv(), obj, name, signature); } inline jmethodID get_static_method_id(JNIEnv *env, jhclass const &cls, const char *name, const char *signature) { return env->GetStaticMethodID(cls.get(), name, signature); } inline jmethodID get_static_method_id(jhclass const &cls, const char *name, const char *signature) { return get_static_method_id(xbmc_jnienv(), cls, name, signature); } template jmethodID get_static_method_id(JNIEnv *env, jholder const &obj, const char *name, const char *signature) { return get_static_method_id(env, get_class(env, obj), name, signature); } template jmethodID get_static_method_id(jholder const &obj, const char *name, const char *signature) { return get_static_method_id(xbmc_jnienv(), obj, name, signature); } inline jfieldID get_field_id(JNIEnv *env, jhclass const &cls, const char *name, const char *signature) { return env->GetFieldID(cls.get(), name, signature); } inline jfieldID get_field_id(jhclass const &cls, const char *name, const char *signature) { return get_field_id(xbmc_jnienv(), cls, name, signature); } template jfieldID get_field_id(JNIEnv *env, jholder const &obj, const char *name, const char *signature) { return get_field_id(env, get_class(env, obj), name, signature); } template jfieldID get_field_id(jholder const &obj, const char *name, const char *signature) { return get_field_id(xbmc_jnienv(), obj, name, signature); } inline jfieldID get_static_field_id(JNIEnv *env, jhclass const &cls, const char *name, const char *signature) { return env->GetStaticFieldID(cls.get(), name, signature); } inline jfieldID get_static_field_id(jhclass const &cls, const char *name, const char *signature) { return get_static_field_id(xbmc_jnienv(), cls, name, signature); } template jfieldID get_static_field_id(JNIEnv *env, jholder const &obj, const char *name, const char *signature) { return get_static_field_id(env, get_class(env, obj), name, signature); } template jfieldID get_static_field_id(jholder const &obj, const char *name, const char *signature) { return get_static_field_id(xbmc_jnienv(), obj, name, signature); } namespace details { void call_void_method(JNIEnv *env, jclass cls, jmethodID mid, ...); void call_void_method(JNIEnv *env, jobject obj, jmethodID mid, ...); jhobject new_object(JNIEnv *env, jclass cls, jmethodID mid, ...); #define CRYSTAX_PP_STEP(type) \ type get_ ## type ## _field(JNIEnv *env, jobject obj, jfieldID fid); \ type get_ ## type ## _field(JNIEnv *env, jclass cls, jfieldID fid); \ type get_static_ ## type ## _field(JNIEnv *env, jobject obj, jfieldID fid); \ type get_static_ ## type ## _field(JNIEnv *env, jclass cls, jfieldID fid); \ void set_ ## type ## _field(JNIEnv *env, jobject obj, jfieldID fid, type const &arg); \ void set_ ## type ## _field(JNIEnv *env, jclass cls, jfieldID fid, type const &arg); \ type call_ ## type ## _method(JNIEnv *env, jclass cls, jmethodID mid, ...); \ type call_ ## type ## _method(JNIEnv *env, jobject obj, jmethodID mid, ...); #include "jni.inc" #undef CRYSTAX_PP_STEP #define CRYSTAX_PP_STEP(type) inline type raw_arg(type arg) {return arg;} CRYSTAX_PP_STEP(jboolean) CRYSTAX_PP_STEP(jbyte) CRYSTAX_PP_STEP(jchar) CRYSTAX_PP_STEP(jshort) CRYSTAX_PP_STEP(jint) CRYSTAX_PP_STEP(jlong) CRYSTAX_PP_STEP(jfloat) CRYSTAX_PP_STEP(jdouble) CRYSTAX_PP_STEP(jobject) CRYSTAX_PP_STEP(jclass) CRYSTAX_PP_STEP(jstring) CRYSTAX_PP_STEP(jthrowable) CRYSTAX_PP_STEP(jarray) CRYSTAX_PP_STEP(jbooleanArray) CRYSTAX_PP_STEP(jbyteArray) CRYSTAX_PP_STEP(jshortArray) CRYSTAX_PP_STEP(jintArray) CRYSTAX_PP_STEP(jlongArray) CRYSTAX_PP_STEP(jfloatArray) CRYSTAX_PP_STEP(jdoubleArray) CRYSTAX_PP_STEP(jobjectArray) #undef CRYSTAX_PP_STEP template T raw_arg(jholder const &arg) { return arg.get(); } template struct jni_helper; template <> struct jni_helper { template static void call_method(JNIEnv *env, T const &obj, jmethodID mid, Args&&... args) { details::call_void_method(env, raw_arg(obj), mid, raw_arg(args)...); } }; struct jni_stripper { template static jhobject new_object(JNIEnv *env, const jhclass &cls, jmethodID mid, Args&&... args) { return details::new_object(env, raw_arg(cls), mid, raw_arg(args)...); } }; #define CRYSTAX_PP_STEP(type) \ template <> \ struct jni_helper \ { \ template \ static type get_field(JNIEnv *env, T const &obj, jfieldID fid) \ { \ return details::get_ ## type ## _field(env, raw_arg(obj), fid); \ } \ template \ static type get_static_field(JNIEnv *env, T const &obj, jfieldID fid) \ { \ return details::get_static_ ## type ## _field(env, raw_arg(obj), fid); \ } \ template \ static void set_field(JNIEnv *env, T const &obj, jfieldID fid, type const &arg) \ { \ details::set_ ## type ## _field(env, raw_arg(obj), fid, arg); \ } \ template \ static type call_method(JNIEnv *env, T const &obj, jmethodID mid, Args&&... args) \ { \ return details::call_ ## type ## _method(env, raw_arg(obj), mid, raw_arg(args)...); \ } \ }; #include "jni.inc" #undef CRYSTAX_PP_STEP template struct jni_signature { static const char *signature; }; } // namespace details // Get field template Ret get_field(JNIEnv *env, jholder const &obj, jfieldID fid) { return details::jni_helper::get_field(env, obj, fid); } template Ret get_field(jholder const &obj, jfieldID fid) { return get_field(xbmc_jnienv(), obj, fid); } template Ret get_field(JNIEnv *env, const char *clsname, jfieldID fid) { return get_field(env, find_class(env, clsname), fid); } template Ret get_field(const char *clsname, jfieldID fid) { return get_field(xbmc_jnienv(), clsname, fid); } template Ret get_field(JNIEnv *env, jholder const &obj, const char *name, const char *signature) { return get_field(env, obj, get_field_id(env, obj, name, signature)); } template Ret get_field(jholder const &obj, const char *name, const char *signature) { return get_field(xbmc_jnienv(), obj, name, signature); } /* template Ret get_field(JNIEnv *env, const char *clsname, const char *name, const char *signature) { return get_field(env, find_class(clsname), name, signature); } template Ret get_field(const char *clsname, const char *name, const char *signature) { return get_field(xbmc_jnienv(), clsname, name, signature); } */ template Ret get_field(JNIEnv *env, jholder const &obj, const char *name) { return get_field(env, obj, name, details::jni_signature::signature); } template Ret get_field(jholder const &obj, const char *name) { return get_field(xbmc_jnienv(), obj, name); } /* template Ret get_field(JNIEnv *env, const char *clsname, const char *name) { return get_field(env, find_class(env, clsname), name); } template Ret get_field(const char *clsname, const char *name) { return get_field(xbmc_jnienv(), clsname, name); } */ // Get static field template Ret get_static_field(JNIEnv *env, jhclass const &cls, jfieldID fid) { return details::jni_helper::get_static_field(env, cls, fid); } template Ret get_static_field(JNIEnv *env, jhobject const &obj, const char *name, const char *signature) { return details::jni_helper::get_static_field(env, get_class(env, obj), get_static_field_id(env, obj, name, signature)); } template Ret get_static_field(JNIEnv *env, jhclass const &cls, const char *name, const char *signature) { return get_static_field(env, cls, get_static_field_id(env, cls, name, signature)); } template Ret get_static_field(jholder const &obj, const char *name, const char *signature) { return get_static_field(xbmc_jnienv(), obj, name, signature); } template Ret get_static_field(JNIEnv *env, const char *clsname, const char *name, const char *signature) { return get_static_field(env, find_class(env, clsname), name, signature); } template Ret get_static_field(const char *clsname, const char *name, const char *signature) { return get_static_field(xbmc_jnienv(), clsname, name, signature); } template Ret get_static_field(JNIEnv *env, jholder const &obj, const char *name) { return get_static_field(env, obj, name, details::jni_signature::signature); } template Ret get_static_field(jholder const &obj, const char *name) { return get_static_field(xbmc_jnienv(), obj, name); } template Ret get_static_field(JNIEnv *env, const char *clsname, const char *name) { return get_static_field(env, find_class(env, clsname), name); } template Ret get_static_field(const char *clsname, const char *name) { return get_static_field(xbmc_jnienv(), clsname, name); } template Ret get_static_field(jhclass const &cls, jfieldID fid) { return details::jni_helper::get_static_field(xbmc_jnienv(), cls, fid); } // Set field template void set_field(JNIEnv *env, jholder const &obj, jfieldID fid, Arg const &arg) { details::jni_helper::set_field(env, obj, fid, arg); } template void set_field(jholder const &obj, jfieldID fid, Arg const &arg) { set_field(xbmc_jnienv(), obj, fid, arg); } template void set_field(JNIEnv *env, const char *clsname, jfieldID fid, Arg const &arg) { set_field(env, find_class(env, clsname), fid, arg); } template void set_field(const char *clsname, jfieldID fid, Arg const &arg) { set_field(xbmc_jnienv(), clsname, fid, arg); } template void set_field(JNIEnv *env, jholder const &obj, const char *name, const char *signature, Arg const &arg) { set_field(env, obj, get_field_id(env, obj, name, signature), arg); } template void set_field(jholder const &obj, const char *name, const char *signature, Arg const &arg) { set_field(xbmc_jnienv(), obj, name, signature, arg); } template void set_field(JNIEnv *env, const char *clsname, const char *name, const char *signature, Arg const &arg) { set_field(env, find_class(env, clsname), name, signature, arg); } template void set_field(const char *clsname, const char *name, const char *signature, Arg const &arg) { set_field(xbmc_jnienv(), clsname, name, signature, arg); } template void set_field(JNIEnv *env, jholder const &obj, const char *name, Arg const &arg) { set_field(env, obj, name, details::jni_signature::signature, arg); } template void set_field(jholder const &obj, const char *name, Arg const &arg) { set_field(xbmc_jnienv(), obj, name, arg); } template void set_field(JNIEnv *env, const char *clsname, const char *name, Arg const &arg) { set_field(env, find_class(env, clsname), name, arg); } template void set_field(const char *clsname, const char *name, Arg const &arg) { set_field(xbmc_jnienv(), clsname, name, arg); } // Set static field template void set_static_field(JNIEnv *env, jholder const &obj, const char *name, const char *signature, Arg const &arg) { set_field(env, obj, get_static_field_id(env, obj, name, signature), arg); } template void set_static_field(jholder const &obj, const char *name, const char *signature, Arg const &arg) { set_static_field(xbmc_jnienv(), obj, name, signature, arg); } template void set_static_field(JNIEnv *env, const char *clsname, const char *name, const char *signature, Arg const &arg) { set_static_field(env, find_class(env, clsname), name, signature, arg); } template void set_static_field(const char *clsname, const char *name, const char *signature, Arg const &arg) { set_static_field(xbmc_jnienv(), clsname, name, signature, arg); } template void set_static_field(JNIEnv *env, jholder const &obj, const char *name, Arg const &arg) { set_static_field(env, obj, name, details::jni_signature::signature, arg); } template void set_static_field(jholder const &obj, const char *name, Arg const &arg) { set_static_field(xbmc_jnienv(), obj, name, arg); } template void set_static_field(JNIEnv *env, const char *clsname, const char *name, Arg const &arg) { set_static_field(env, find_class(env, clsname), name, arg); } template void set_static_field(const char *clsname, const char *name, Arg const &arg) { set_static_field(xbmc_jnienv(), clsname, name, arg); } // Warning!!! C++11 magic below: variadic templates and perfect forwarding! // We need to define own implementation of std::forward because we don't have // standard C++ library when building libcrystax. namespace details { #if __GNUC__ == 4 && __GNUC_MINOR__ == 4 template struct identity {typedef T type;}; template inline T && forward(typename identity::type && arg) { return arg; } #else // __GNUC__ == 4 && __GNUC_MINOR__ == 4 template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template struct remove_reference { typedef T type; }; template struct is_lvalue_reference { enum {value = false}; }; template struct is_lvalue_reference { enum {value = true}; }; template inline T && forward(typename remove_reference::type &arg) { return static_cast(arg); } template inline T && forward(typename remove_reference::type &&arg) { static_assert(!is_lvalue_reference::value, "template argument is an lvalue reference type"); return static_cast(arg); } #endif // __GNUC__ == 4 && __GNUC_MINOR__ == 4 } // namespace details template Ret call_method(JNIEnv *env, T const &obj, jmethodID mid, Args&&... args) { return details::jni_helper::call_method(env, obj, mid, details::forward(args)...); } template Ret call_static_method(JNIEnv *env, const jhclass &cls, const jmethodID mid, Args&&... args) { return details::jni_helper::call_static_method(env, cls, mid, details::forward(args)...); } template jhobject new_object(JNIEnv *env, const jhclass &cls, jmethodID mid, Args&&... args) { return details::jni_stripper::new_object(env, cls, mid, details::forward(args)...); } template Ret call_method(T const &obj, jmethodID mid, Args&&... args) { return call_method(xbmc_jnienv(), obj, mid, details::forward(args)...); } template Ret call_method(JNIEnv *env, const char *clsname, jmethodID mid, Args&&... args) { return call_method(env, find_class(env, clsname), mid, details::forward(args)...); } template Ret call_method(const char *clsname, jmethodID mid, Args&&... args) { return call_method(xbmc_jnienv(), clsname, mid, details::forward(args)...); } template Ret call_method(JNIEnv *env, T const &obj, const char *name, const char *signature, Args&&... args) { return call_method(env, obj, get_method_id(env, obj, name, signature), details::forward(args)...); } template Ret call_method(T const &obj, const char *name, const char *signature, Args&&... args) { return call_method(xbmc_jnienv(), obj, name, signature, details::forward(args)...); } template Ret call_method(JNIEnv *env, const char *clsname, const char *name, const char *signature, Args&&... args) { return call_method(env, find_class(env, clsname), name, signature, details::forward(args)...); } template Ret call_method(const char *clsname, const char *name, const char *signature, Args&&... args) { return call_method(xbmc_jnienv(), clsname, name, signature, details::forward(args)...); } template Ret call_static_method(JNIEnv *env, const jhclass &clazz, const char *name, const char *signature, Args&&... args) { return call_method(env, clazz, get_static_method_id(env, clazz, name, signature), details::forward(args)...); } template Ret call_static_method(jhclass const &clazz, const char *name, const char *signature, Args&&... args) { return call_static_method(xbmc_jnienv(), clazz, name, signature, details::forward(args)...); } template Ret call_static_method(JNIEnv *env, const char *clsname, const char *name, const char *signature, Args&&... args) { return call_static_method(env, find_class(env, clsname), name, signature, details::forward(args)...); } template Ret call_static_method(const char *clsname, const char *name, const char *signature, Args&&... args) { return call_static_method(xbmc_jnienv(), clsname, name, signature, details::forward(args)...); } template jhobject new_object(JNIEnv *env, const jhclass &cls, const char *name, const char *signature, Args&&... args) { return new_object(env, cls, get_method_id(env, cls, name, signature), details::forward(args)...); } template jhobject new_object(JNIEnv *env, const char *clsname, const char *name, const char *signature, Args&&... args) { return new_object(env, find_class(env, clsname), name, signature, details::forward(args)...); } template jhobject new_object(const char *clsname, const char *name, const char *signature, Args&&... args) { return new_object(xbmc_jnienv(), clsname, name, signature, details::forward(args)...); } template jhobject new_object(std::string clsname, const char *name, const char *signature, Args&&... args) { return new_object(xbmc_jnienv(), clsname.c_str(), name, signature, details::forward(args)...); } template jhobject new_object(const char *clsname) { return new_object(xbmc_jnienv(), clsname, "", "()V"); } template jhobject new_object(std::string clsname) { return new_object(xbmc_jnienv(), clsname.c_str(), "", "()V"); } template jhobject new_object(const jhclass& cls, const char *name, const char *signature, Args&&... args) { return new_object(xbmc_jnienv(), cls, name, signature, details::forward(args)...); } template jhobject new_object(const jhclass& cls) { return new_object(xbmc_jnienv(), cls, "", "()V"); } inline void jthrow(JNIEnv *env, jhthrowable const &ex) {env->Throw(ex.get());} inline void jthrow(jhthrowable const &ex) {jthrow(xbmc_jnienv(), ex);} inline void jthrow(JNIEnv *env, jhclass const &cls, char const *what) {env->ThrowNew(cls.get(), what);} inline void jthrow(jhclass const &cls, char const *what) {jthrow(xbmc_jnienv(), cls, what);} inline void jthrow(JNIEnv *env, char const *clsname, char const *what) {jthrow(find_class(env, clsname), what);} inline void jthrow(char const *clsname, char const *what) {jthrow(xbmc_jnienv(), clsname, what);} bool jexcheck(JNIEnv *env); inline bool jexcheck() {return jexcheck(xbmc_jnienv());} } // namespace jni