diff options
Diffstat (limited to 'unix/modjni.c')
-rw-r--r-- | unix/modjni.c | 722 |
1 files changed, 0 insertions, 722 deletions
diff --git a/unix/modjni.c b/unix/modjni.c deleted file mode 100644 index b7ac49dc8..000000000 --- a/unix/modjni.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <assert.h> -#include <string.h> -#include <errno.h> -#include <dlfcn.h> -#include <ctype.h> - -#include "py/nlr.h" -#include "py/runtime0.h" -#include "py/runtime.h" -#include "py/binary.h" - -#include <jni.h> - -#define JJ(call, ...) (*env)->call(env, __VA_ARGS__) -#define JJ1(call) (*env)->call(env) -#define MATCH(s, static) (!strncmp(s, static, sizeof(static) - 1)) - -static JavaVM *jvm; -static JNIEnv *env; -static jclass Class_class; -static jclass String_class; -static jmethodID Class_getName_mid; -static jmethodID Class_getField_mid; -static jmethodID Class_getMethods_mid; -static jmethodID Class_getConstructors_mid; -static jmethodID Method_getName_mid; -static jmethodID Object_toString_mid; - -static jclass List_class; -static jmethodID List_get_mid; -static jmethodID List_set_mid; -static jmethodID List_size_mid; - -static jclass IndexException_class; - -STATIC const mp_obj_type_t jobject_type; -STATIC const mp_obj_type_t jmethod_type; - -STATIC mp_obj_t new_jobject(jobject jo); -STATIC mp_obj_t new_jclass(jclass jc); -STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args); -STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out); - -typedef struct _mp_obj_jclass_t { - mp_obj_base_t base; - jclass cls; -} mp_obj_jclass_t; - -typedef struct _mp_obj_jobject_t { - mp_obj_base_t base; - jobject obj; -} mp_obj_jobject_t; - -typedef struct _mp_obj_jmethod_t { - mp_obj_base_t base; - jobject obj; - jmethodID meth; - qstr name; - bool is_static; -} mp_obj_jmethod_t; - -// Utility functions - -STATIC bool is_object_type(const char *jtypesig) { - while (*jtypesig != ' ' && *jtypesig) { - if (*jtypesig == '.') { - return true; - } - jtypesig++; - } - return false; -} - -STATIC void check_exception(void) { - jobject exc = JJ1(ExceptionOccurred); - if (exc) { - //JJ1(ExceptionDescribe); - mp_obj_t py_e = new_jobject(exc); - JJ1(ExceptionClear); - if (JJ(IsInstanceOf, exc, IndexException_class)) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, py_e)); - } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_Exception, py_e)); - } -} - -STATIC void print_jobject(const mp_print_t *print, jobject obj) { - jobject str_o = JJ(CallObjectMethod, obj, Object_toString_mid); - const char *str = JJ(GetStringUTFChars, str_o, NULL); - mp_printf(print, str); - JJ(ReleaseStringUTFChars, str_o, str); -} - -// jclass - -STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - mp_obj_jclass_t *self = self_in; - if (kind == PRINT_REPR) { - mp_printf(print, "<jclass @%p \"", self->cls); - } - print_jobject(print, self->cls); - if (kind == PRINT_REPR) { - mp_printf(print, "\">"); - } -} - -STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { - if (dest[0] == MP_OBJ_NULL) { - // load attribute - mp_obj_jclass_t *self = self_in; - const char *attr = qstr_str(attr_in); - - jstring field_name = JJ(NewStringUTF, attr); - jobject field = JJ(CallObjectMethod, self->cls, Class_getField_mid, field_name); - if (!JJ1(ExceptionCheck)) { - jfieldID field_id = JJ(FromReflectedField, field); - jobject obj = JJ(GetStaticObjectField, self->cls, field_id); - dest[0] = new_jobject(obj); - return; - } - //JJ1(ExceptionDescribe); - JJ1(ExceptionClear); - - mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); - o->base.type = &jmethod_type; - o->name = attr_in; - o->meth = NULL; - o->obj = self->cls; - o->is_static = true; - dest[0] = o; - } -} - -STATIC mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - if (n_kw != 0) { - mp_raise_TypeError("kwargs not supported"); - } - mp_obj_jclass_t *self = self_in; - - jarray methods = JJ(CallObjectMethod, self->cls, Class_getConstructors_mid); - - return call_method(self->cls, NULL, methods, true, n_args, args); -} - -STATIC const mp_rom_map_elem_t jclass_locals_dict_table[] = { -// { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, -// { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); - -STATIC const mp_obj_type_t jclass_type = { - { &mp_type_type }, - .name = MP_QSTR_jclass, - .print = jclass_print, - .attr = jclass_attr, - .call = jclass_call, - .locals_dict = (mp_obj_dict_t*)&jclass_locals_dict, -}; - -STATIC mp_obj_t new_jclass(jclass jc) { - mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t); - o->base.type = &jclass_type; - o->cls = jc; - return o; -} - -// jobject - -STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - mp_obj_jobject_t *self = self_in; - if (kind == PRINT_REPR) { - mp_printf(print, "<jobject @%p \"", self->obj); - } - print_jobject(print, self->obj); - if (kind == PRINT_REPR) { - mp_printf(print, "\">"); - } -} - -STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { - if (dest[0] == MP_OBJ_NULL) { - // load attribute - mp_obj_jobject_t *self = self_in; - - const char *attr = qstr_str(attr_in); - jclass obj_class = JJ(GetObjectClass, self->obj); - jstring field_name = JJ(NewStringUTF, attr); - jobject field = JJ(CallObjectMethod, obj_class, Class_getField_mid, field_name); - JJ(DeleteLocalRef, field_name); - JJ(DeleteLocalRef, obj_class); - if (!JJ1(ExceptionCheck)) { - jfieldID field_id = JJ(FromReflectedField, field); - JJ(DeleteLocalRef, field); - jobject obj = JJ(GetObjectField, self->obj, field_id); - dest[0] = new_jobject(obj); - return; - } - //JJ1(ExceptionDescribe); - JJ1(ExceptionClear); - - mp_obj_jmethod_t *o = m_new_obj(mp_obj_jmethod_t); - o->base.type = &jmethod_type; - o->name = attr_in; - o->meth = NULL; - o->obj = self->obj; - o->is_static = false; - dest[0] = o; - } -} - -STATIC void get_jclass_name(jobject obj, char *buf) { - jclass obj_class = JJ(GetObjectClass, obj); - jstring name = JJ(CallObjectMethod, obj_class, Class_getName_mid); - jint len = JJ(GetStringLength, name); - JJ(GetStringUTFRegion, name, 0, len, buf); - check_exception(); -} - -STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { - mp_obj_jobject_t *self = self_in; - mp_uint_t idx = mp_obj_get_int(index); - char class_name[64]; - get_jclass_name(self->obj, class_name); - //printf("class: %s\n", class_name); - - if (class_name[0] == '[') { - if (class_name[1] == 'L' || class_name[1] == '[') { - if (value == MP_OBJ_NULL) { - // delete - assert(0); - } else if (value == MP_OBJ_SENTINEL) { - // load - jobject el = JJ(GetObjectArrayElement, self->obj, idx); - return new_jobject(el); - } else { - // store - jvalue jval; - const char *t = class_name + 1; - py2jvalue(&t, value, &jval); - JJ(SetObjectArrayElement, self->obj, idx, jval.l); - return mp_const_none; - } - } - mp_raise_NotImplementedError(""); - } - - if (!JJ(IsInstanceOf, self->obj, List_class)) { - return MP_OBJ_NULL; - } - - - if (value == MP_OBJ_NULL) { - // delete - assert(0); - } else if (value == MP_OBJ_SENTINEL) { - // load - jobject el = JJ(CallObjectMethod, self->obj, List_get_mid, idx); - check_exception(); - return new_jobject(el); - } else { - // store - assert(0); - } - - -return MP_OBJ_NULL; -} - -STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - mp_obj_jobject_t *self = self_in; - switch (op) { - case MP_UNARY_OP_BOOL: - case MP_UNARY_OP_LEN: { - jint len = JJ(CallIntMethod, self->obj, List_size_mid); - if (op == MP_UNARY_OP_BOOL) { - return mp_obj_new_bool(len != 0); - } - return MP_OBJ_NEW_SMALL_INT(len); - } - default: - return MP_OBJ_NULL; // op not supported - } -} - -// TODO: subscr_load_adaptor & subscr_getiter convenience functions -// should be moved to common location for reuse. -STATIC mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { - return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL); -} -MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor); - -// .getiter special method which returns iterator which works in terms -// of object subscription. -STATIC mp_obj_t subscr_getiter(mp_obj_t self_in) { - mp_obj_t dest[2] = {(mp_obj_t)&subscr_load_adaptor_obj, self_in}; - return mp_obj_new_getitem_iter(dest); -} - -STATIC const mp_obj_type_t jobject_type = { - { &mp_type_type }, - .name = MP_QSTR_jobject, - .print = jobject_print, - .unary_op = jobject_unary_op, - .attr = jobject_attr, - .subscr = jobject_subscr, - .getiter = subscr_getiter, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; - -STATIC mp_obj_t new_jobject(jobject jo) { - if (jo == NULL) { - return mp_const_none; - } else if (JJ(IsInstanceOf, jo, String_class)) { - const char *s = JJ(GetStringUTFChars, jo, NULL); - mp_obj_t ret = mp_obj_new_str(s, strlen(s), false); - JJ(ReleaseStringUTFChars, jo, s); - return ret; - } else if (JJ(IsInstanceOf, jo, Class_class)) { - return new_jclass(jo); - } else { - mp_obj_jobject_t *o = m_new_obj(mp_obj_jobject_t); - o->base.type = &jobject_type; - o->obj = jo; - return o; - } - -} - - -// jmethod - -STATIC void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_jmethod_t *self = self_in; - // Variable value printed as cast to int - mp_printf(print, "<jmethod '%s'>", qstr_str(self->name)); -} - -#define IMATCH(s, static) ((!strncmp(s, static, sizeof(static) - 1)) && (s += sizeof(static) - 1)) - -#define CHECK_TYPE(java_type_name) \ - if (strncmp(arg_type, java_type_name, sizeof(java_type_name) - 1) != 0) { \ - return false; \ - } \ - arg_type += sizeof(java_type_name) - 1; - -STATIC const char *strprev(const char *s, char c) { - while (*s != c) { - s--; - } - return s; -} - -STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { - const char *arg_type = *jtypesig; - mp_obj_type_t *type = mp_obj_get_type(arg); - - if (type == &mp_type_str) { - if (IMATCH(arg_type, "java.lang.String") || IMATCH(arg_type, "java.lang.Object")) { - out->l = JJ(NewStringUTF, mp_obj_str_get_str(arg)); - } else { - return false; - } - } else if (type == &mp_type_int) { - if (IMATCH(arg_type, "int") || IMATCH(arg_type, "long")) { - // TODO: Java long is 64-bit actually - out->j = mp_obj_get_int(arg); - } else { - return false; - } - } else if (type == &jobject_type) { - bool is_object = false; - const char *expected_type = arg_type; - while (1) { - if (isalpha(*arg_type)) { - } else if (*arg_type == '.') { - is_object = true; - } else { - break; - } - arg_type++; - } - if (!is_object) { - return false; - } - mp_obj_jobject_t *jo = arg; - if (!MATCH(expected_type, "java.lang.Object")) { - char class_name[64]; - get_jclass_name(jo->obj, class_name); - //printf("Arg class: %s\n", class_name); - if (strcmp(class_name, expected_type) != 0) { - return false; - } - } - out->l = jo->obj; - } else if (type == &mp_type_bool) { - if (IMATCH(arg_type, "boolean")) { - out->z = arg == mp_const_true; - } else { - return false; - } - } else if (arg == mp_const_none) { - //printf("TODO: Check java arg type!!\n"); - while (isalpha(*arg_type) || *arg_type == '.') { - arg_type++; - } - out->l = NULL; - } else { - mp_raise_TypeError("arg type not supported"); - } - - *jtypesig = arg_type; - return true; -} - -#if 0 -// jvalue is known to be union of jobject and friends. And yet from C's -// perspective, it's aggregate object which may require passing via stack -// instead of registers. Work that around by passing jobject and typecasting -// it. -STATIC mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { - if (arg == NULL || MATCH(jtypesig, "void")) { - return mp_const_none; - } else if (MATCH(jtypesig, "boolean")) { - return mp_obj_new_bool((bool)arg); - } else if (MATCH(jtypesig, "int")) { - return mp_obj_new_int((mp_int_t)arg); - } else if (is_object_type(jtypesig)) { - // Non-primitive, object type - return new_jobject(arg); - } - - printf("Unknown return type: %s\n", jtypesig); - - return MP_OBJ_NULL; -} -#endif - -STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args) { - jvalue jargs[n_args]; -// printf("methods=%p\n", methods); - jsize num_methods = JJ(GetArrayLength, methods); - for (int i = 0; i < num_methods; i++) { - jobject meth = JJ(GetObjectArrayElement, methods, i); - jobject name_o = JJ(CallObjectMethod, meth, Object_toString_mid); - const char *decl = JJ(GetStringUTFChars, name_o, NULL); - const char *arg_types = strchr(decl, '(') + 1; - //const char *arg_types_end = strchr(arg_types, ')'); -// printf("method[%d]=%p %s\n", i, meth, decl); - - const char *meth_name = NULL; - const char *ret_type = NULL; - if (!is_constr) { - meth_name = strprev(arg_types, '.') + 1; - ret_type = strprev(meth_name, ' ') - 1; - ret_type = strprev(ret_type, ' ') + 1; - - int name_len = strlen(name); - if (strncmp(name, meth_name, name_len/*arg_types - meth_name - 1*/) || meth_name[name_len] != '('/*(*/) { - goto next_method; - } - } -// printf("method[%d]=%p %s\n", i, meth, decl); -// printf("!!!%s\n", arg_types); -// printf("name=%p meth_name=%s\n", name, meth_name); - - bool found = true; - for (int i = 0; i < n_args && *arg_types != ')'; i++) { - if (!py2jvalue(&arg_types, args[i], &jargs[i])) { - goto next_method; - } - - if (*arg_types == ',') { - arg_types++; - } - } - - if (*arg_types != ')') { - goto next_method; - } - - if (found) { -// printf("found!\n"); - jmethodID method_id = JJ(FromReflectedMethod, meth); - jobject res; - mp_obj_t ret; - if (is_constr) { - JJ(ReleaseStringUTFChars, name_o, decl); - res = JJ(NewObjectA, obj, method_id, jargs); - return new_jobject(res); - } else { - if (MATCH(ret_type, "void")) { - JJ(CallVoidMethodA, obj, method_id, jargs); - check_exception(); - ret = mp_const_none; - } else if (MATCH(ret_type, "int")) { - jint res = JJ(CallIntMethodA, obj, method_id, jargs); - check_exception(); - ret = mp_obj_new_int(res); - } else if (MATCH(ret_type, "boolean")) { - jboolean res = JJ(CallBooleanMethodA, obj, method_id, jargs); - check_exception(); - ret = mp_obj_new_bool(res); - } else if (is_object_type(ret_type)) { - res = JJ(CallObjectMethodA, obj, method_id, jargs); - check_exception(); - ret = new_jobject(res); - } else { - JJ(ReleaseStringUTFChars, name_o, decl); - mp_raise_TypeError("cannot handle return type"); - } - - JJ(ReleaseStringUTFChars, name_o, decl); - JJ(DeleteLocalRef, name_o); - JJ(DeleteLocalRef, meth); - return ret; - } - } - -next_method: - JJ(ReleaseStringUTFChars, name_o, decl); - JJ(DeleteLocalRef, name_o); - JJ(DeleteLocalRef, meth); - } - - mp_raise_TypeError("method not found"); -} - - -STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - if (n_kw != 0) { - mp_raise_TypeError("kwargs not supported"); - } - mp_obj_jmethod_t *self = self_in; - - const char *name = qstr_str(self->name); -// jstring meth_name = JJ(NewStringUTF, name); - - jclass obj_class = self->obj; - if (!self->is_static) { - obj_class = JJ(GetObjectClass, self->obj); - } - jarray methods = JJ(CallObjectMethod, obj_class, Class_getMethods_mid); - - return call_method(self->obj, name, methods, false, n_args, args); -} - -STATIC const mp_obj_type_t jmethod_type = { - { &mp_type_type }, - .name = MP_QSTR_jmethod, - .print = jmethod_print, - .call = jmethod_call, -// .attr = jobject_attr, -// .locals_dict = (mp_obj_dict_t*)&jobject_locals_dict, -}; - -#ifdef __ANDROID__ -#define LIBJVM_SO "libdvm.so" -#else -#define LIBJVM_SO "libjvm.so" -#endif - -STATIC void create_jvm() { - JavaVMInitArgs args; - JavaVMOption options; - options.optionString = "-Djava.class.path=."; - args.version = JNI_VERSION_1_6; - args.nOptions = 1; - args.options = &options; - args.ignoreUnrecognized = 0; - - if (env) { - return; - } - - void *libjvm = dlopen(LIBJVM_SO, RTLD_NOW | RTLD_GLOBAL); - if (!libjvm) { - mp_raise_msg(&mp_type_OSError, "unable to load libjvm.so, use LD_LIBRARY_PATH"); - } - int (*_JNI_CreateJavaVM)(void*, void**, void*) = dlsym(libjvm, "JNI_CreateJavaVM"); - - int st = _JNI_CreateJavaVM(&jvm, (void**)&env, &args); - if (st < 0 || !env) { - mp_raise_msg(&mp_type_OSError, "unable to create JVM"); - } - - Class_class = JJ(FindClass, "java/lang/Class"); - jclass method_class = JJ(FindClass, "java/lang/reflect/Method"); - String_class = JJ(FindClass, "java/lang/String"); - - jclass Object_class = JJ(FindClass, "java/lang/Object"); - Object_toString_mid = JJ(GetMethodID, Object_class, "toString", - "()Ljava/lang/String;"); - - Class_getName_mid = (*env)->GetMethodID(env, Class_class, "getName", - "()Ljava/lang/String;"); - Class_getField_mid = (*env)->GetMethodID(env, Class_class, "getField", - "(Ljava/lang/String;)Ljava/lang/reflect/Field;"); - Class_getMethods_mid = (*env)->GetMethodID(env, Class_class, "getMethods", - "()[Ljava/lang/reflect/Method;"); - Class_getConstructors_mid = (*env)->GetMethodID(env, Class_class, "getConstructors", - "()[Ljava/lang/reflect/Constructor;"); - Method_getName_mid = (*env)->GetMethodID(env, method_class, "getName", - "()Ljava/lang/String;"); - - List_class = JJ(FindClass, "java/util/List"); - List_get_mid = JJ(GetMethodID, List_class, "get", - "(I)Ljava/lang/Object;"); - List_set_mid = JJ(GetMethodID, List_class, "set", - "(ILjava/lang/Object;)Ljava/lang/Object;"); - List_size_mid = JJ(GetMethodID, List_class, "size", - "()I"); - IndexException_class = JJ(FindClass, "java/lang/IndexOutOfBoundsException"); -} - -STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { - const char *cls_name = mp_obj_str_get_str(cls_name_in); - if (!env) { - create_jvm(); - } - jclass cls = JJ(FindClass, cls_name); - - mp_obj_jclass_t *o = m_new_obj(mp_obj_jclass_t); - o->base.type = &jclass_type; - o->cls = cls; - return o; -} -MP_DEFINE_CONST_FUN_OBJ_1(mod_jni_cls_obj, mod_jni_cls); - -STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { - if (!env) { - create_jvm(); - } - mp_int_t size = mp_obj_get_int(size_in); - jobject res = NULL; - - if (MP_OBJ_IS_TYPE(type_in, &jclass_type)) { - - mp_obj_jclass_t *jcls = type_in; - res = JJ(NewObjectArray, size, jcls->cls, NULL); - - } else if (MP_OBJ_IS_STR(type_in)) { - const char *type = mp_obj_str_get_str(type_in); - switch (*type) { - case 'Z': - res = JJ(NewBooleanArray, size); - break; - case 'B': - res = JJ(NewByteArray, size); - break; - case 'C': - res = JJ(NewCharArray, size); - break; - case 'S': - res = JJ(NewShortArray, size); - break; - case 'I': - res = JJ(NewIntArray, size); - break; - case 'J': - res = JJ(NewLongArray, size); - break; - case 'F': - res = JJ(NewFloatArray, size); - break; - case 'D': - res = JJ(NewDoubleArray, size); - break; - } - - } - - return new_jobject(res); -} -MP_DEFINE_CONST_FUN_OBJ_2(mod_jni_array_obj, mod_jni_array); - - -STATIC mp_obj_t mod_jni_env() { - return mp_obj_new_int((mp_int_t)env); -} -MP_DEFINE_CONST_FUN_OBJ_0(mod_jni_env_obj, mod_jni_env); - -STATIC const mp_rom_map_elem_t mp_module_jni_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_jni) }, - { MP_ROM_QSTR(MP_QSTR_cls), MP_ROM_PTR(&mod_jni_cls_obj) }, - { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mod_jni_array_obj) }, - { MP_ROM_QSTR(MP_QSTR_env), MP_ROM_PTR(&mod_jni_env_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_jni_globals, mp_module_jni_globals_table); - -const mp_obj_module_t mp_module_jni = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_jni_globals, -}; |