1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Android jni helpers
12  *
13  *      By Thomas Fjellstrom.
14  *
15  */
16 
17 #include "allegro5/allegro.h"
18 #include "allegro5/internal/aintern_android.h"
19 #include <jni.h>
20 #include <stdarg.h>
21 
22 ALLEGRO_DEBUG_CHANNEL("jni")
23 
24 #define VERBOSE_DEBUG(a, ...) (void)0
25 
26 /* jni helpers */
27 
__jni_checkException(JNIEnv * env,const char * file,const char * func,int line)28 void __jni_checkException(JNIEnv *env, const char *file, const char *func, int line)
29 {
30    jthrowable exc;
31 
32    exc = (*env)->ExceptionOccurred(env);
33    if (exc) {
34       ALLEGRO_DEBUG("GOT AN EXCEPTION @ %s:%i %s", file, line, func);
35       /* We don't do much with the exception, except that
36          we print a debug message for it, clear it, and
37          throw a new exception. */
38       (*env)->ExceptionDescribe(env);
39       (*env)->ExceptionClear(env);
40       (*env)->FatalError(env, "EXCEPTION");
41       //(*env)->ThrowNew(env, system_data.illegal_argument_exception_class, "thrown from C code");
42    }
43 }
44 
_jni_callObjectMethod(JNIEnv * env,jobject object,const char * name,const char * sig)45 jobject _jni_callObjectMethod(JNIEnv *env, jobject object,
46    const char *name, const char *sig)
47 {
48    VERBOSE_DEBUG("%s (%s)", name, sig);
49 
50    jclass class_id = _jni_call(env, jclass, GetObjectClass, object);
51    jmethodID method_id = _jni_call(env, jmethodID, GetMethodID, class_id, name, sig);
52    jobject ret = _jni_call(env, jobject, CallObjectMethod, object, method_id);
53 
54    _jni_callv(env, DeleteLocalRef, class_id);
55 
56    return ret;
57 }
58 
_jni_callObjectMethodV(JNIEnv * env,jobject object,const char * name,const char * sig,...)59 jobject _jni_callObjectMethodV(JNIEnv *env, jobject object,
60    const char *name, const char *sig, ...)
61 {
62    va_list ap;
63 
64    VERBOSE_DEBUG("%s (%s)", name, sig);
65 
66    jclass class_id = _jni_call(env, jclass, GetObjectClass, object);
67    jmethodID method_id = _jni_call(env, jmethodID, GetMethodID, class_id, name, sig);
68 
69    va_start(ap, sig);
70    jobject ret = _jni_call(env, jobject, CallObjectMethodV, object, method_id, ap);
71    va_end(ap);
72 
73    _jni_callv(env, DeleteLocalRef, class_id);
74 
75    VERBOSE_DEBUG("callObjectMethodV end");
76    return ret;
77 }
78 
_jni_getString(JNIEnv * env,jobject object)79 ALLEGRO_USTR *_jni_getString(JNIEnv *env, jobject object)
80 {
81    VERBOSE_DEBUG("GetStringUTFLength");
82    jsize len = _jni_call(env, jsize, GetStringUTFLength, object);
83 
84    const char *str = _jni_call(env, const char *, GetStringUTFChars, object, NULL);
85 
86    VERBOSE_DEBUG("al_ustr_new_from_buffer");
87    ALLEGRO_USTR *ustr = al_ustr_new_from_buffer(str, len);
88 
89    _jni_callv(env, ReleaseStringUTFChars, object, str);
90 
91    return ustr;
92 }
93 
_jni_callStringMethod(JNIEnv * env,jobject obj,const char * name,const char * sig)94 ALLEGRO_USTR *_jni_callStringMethod(JNIEnv *env, jobject obj,
95    const char *name, const char *sig)
96 {
97    jobject str_obj = _jni_callObjectMethod(env, obj, name, sig);
98    return _jni_getString(env, str_obj);
99 }
100 
_jni_callStaticObjectMethodV(JNIEnv * env,jclass cls,const char * name,const char * sig,...)101 jobject _jni_callStaticObjectMethodV(JNIEnv *env, jclass cls,
102    const char *name, const char *sig, ...)
103 {
104    jmethodID mid;
105    jobject ret;
106    va_list ap;
107 
108    mid = _jni_call(env, jmethodID, GetStaticMethodID, cls, name, sig);
109 
110    va_start(ap, sig);
111    ret = _jni_call(env, jobject, CallStaticObjectMethodV, cls, mid, ap);
112    va_end(ap);
113 
114    return ret;
115 }
116 
_jni_callStaticIntMethodV(JNIEnv * env,jclass cls,const char * name,const char * sig,...)117 jint _jni_callStaticIntMethodV(JNIEnv *env, jclass cls,
118    const char *name, const char *sig, ...)
119 {
120    jmethodID mid;
121    jint ret;
122    va_list ap;
123 
124    mid = _jni_call(env, jmethodID, GetStaticMethodID, cls, name, sig);
125 
126    va_start(ap, sig);
127    ret = _jni_call(env, jint, CallStaticIntMethodV, cls, mid, ap);
128    va_end(ap);
129 
130    return ret;
131 }
132 
133 /* vim: set sts=3 sw=3 et: */
134