From 9b9a799e26d30cb1f11d9823636afbc503dd4063 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini <sylvain.berfini@belledonne-communications.com> Date: Wed, 19 Jan 2022 11:43:16 +0100 Subject: [PATCH] Added support for enum lists in java wrapper --- tools/abstractapi.py | 2 +- wrappers/java/genwrapper.py | 25 +++++++++++++++++++++---- wrappers/java/java_class.mustache | 2 +- wrappers/java/java_enum.mustache | 18 ++++++++++++++++++ wrappers/java/jni.mustache | 22 +++++++++++++++++++--- 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/tools/abstractapi.py b/tools/abstractapi.py index f872404123..80c7e9526a 100644 --- a/tools/abstractapi.py +++ b/tools/abstractapi.py @@ -1281,7 +1281,7 @@ class JavaLangTranslator(CLikeLangTranslator): return 'jobjectArray' return _type.containedTypeDesc.translate(self, jni=True) + 'Array' elif type(_type.containedTypeDesc) is EnumType: - ptrtype = _type.containedTypeDesc.translate(self, native=native) + return 'jintArray' ptrtype = '' if type(_type.containedTypeDesc) is ClassType: ptrtype = _type.containedTypeDesc.translate(self, native=native, namespace=namespace) diff --git a/wrappers/java/genwrapper.py b/wrappers/java/genwrapper.py index ce1570e746..22e0d5563a 100755 --- a/wrappers/java/genwrapper.py +++ b/wrappers/java/genwrapper.py @@ -245,13 +245,22 @@ class JavaTranslator: def generate_set_listener(self, _class): return self.generate_listener('setListener', _class) + def translate_method_native_arg(self, arg, namespace): + if type(arg.type) is AbsApi.EnumType: + return arg.name.translate(self.nameTranslator) + '.toInt()' + elif type(arg.type) is AbsApi.ListType and isinstance(arg.type.containedTypeDesc, AbsApi.EnumType): + typename = arg.type.translate(self.langTranslator, isReturn=True, namespace=namespace) + return typename[:-2] + '.toIntArray(' + arg.name.translate(self.nameTranslator) + ')' + return arg.name.translate(self.nameTranslator) + def translate_method(self, _method, _hasCoreAccessor=False, _forceMethodName=""): methodDict = {} namespace = _method.find_first_ancestor_by_type(AbsApi.Namespace) methodDict['return'] = _method.returnType.translate(self.langTranslator, isReturn=True, namespace=namespace, exceptionEnabled=self.exceptions) - isArray = _method.returnType.translate(self.langTranslator, jni=True, isReturn=True, namespace=namespace) == 'jobjectArray' + native_type = _method.returnType.translate(self.langTranslator, jni=True, isReturn=True, namespace=namespace) + isArray = native_type == 'jobjectArray' or native_type == 'jintArray' # Wrapper takes care or never returning a null array even if the doc says it can return a null list methodDict['return_maybenil'] = _method.maybenil and not isArray methodDict['return_notnil'] = _method.notnil or isArray @@ -276,13 +285,17 @@ class JavaTranslator: methodDict['exception'] = self.throws_exception(_method.returnType) methodDict['enumCast'] = type(_method.returnType) is AbsApi.EnumType + methodDict['enumArrayCast'] = type(_method.returnType) is AbsApi.ListType and isinstance(_method.returnType.containedTypeDesc, AbsApi.EnumType) + methodDict['enumName'] = "" + if methodDict['enumArrayCast']: + methodDict['enumName'] = methodDict['return'][:-2] methodDict['classCast'] = type(_method.returnType) is AbsApi.ClassType methodDict['params'] = ', '.join(['{0}{1}'.format('@Nullable ' if arg.maybenil else '@NonNull ' if arg.notnil else '', arg.translate(self.langTranslator, namespace=namespace)) for arg in _method.args]) methodDict['native_params'] = ', '.join(['long nativePtr'] + [arg.translate(self.langTranslator, native=True, namespace=namespace) for arg in _method.args]) methodDict['static_native_params'] = ', '.join([arg.translate(self.langTranslator, native=True, namespace=namespace) for arg in _method.args]) methodDict['native_params_impl'] = ', '.join( - ['nativePtr'] + [arg.name.translate(self.nameTranslator) + ('.toInt()' if type(arg.type) is AbsApi.EnumType else '') for arg in _method.args]) + ['nativePtr'] + [self.translate_method_native_arg(arg, namespace) for arg in _method.args]) methodDict['deprecated'] = _method.deprecated methodDict['briefDoc'] = _method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if _method.briefDescription is not None else None @@ -314,7 +327,7 @@ class JavaTranslator: methodDict['needLjb'] = False methodDict['return'] = _method.returnType.translate(self.langTranslator, jni=True, isReturn=True, namespace=namespace) - methodDict['hasListReturn'] = methodDict['return'] == 'jobjectArray' + methodDict['hasListReturn'] = methodDict['return'] == 'jobjectArray' or methodDict['return'] == 'jintArray' methodDict['hasByteArrayReturn'] = methodDict['return'] == 'jbyteArray' methodDict['hasReturn'] = not methodDict['return'] == 'void' and not methodDict['hasListReturn'] and not methodDict['hasByteArrayReturn'] methodDict['hasStringReturn'] = methodDict['return'] == 'jstring' @@ -345,6 +358,7 @@ class JavaTranslator: methodDict['returnClassName'] = _method.returnType.translate(self.langTranslator, namespace=namespace) methodDict['isRealObjectArray'] = False methodDict['isStringObjectArray'] = False + methodDict['isEnumObjectArray'] = False methodDict['c_type_return'] = _method.returnType.translate(self.clangTranslator) if methodDict['c_name'] in jni_blacklist: @@ -355,6 +369,8 @@ class JavaTranslator: methodDict['isStringObjectArray'] = True elif isinstance(_method.returnType.containedTypeDesc, AbsApi.BaseType): methodDict['isStringObjectArray'] = True + elif isinstance(_method.returnType.containedTypeDesc, AbsApi.EnumType): + methodDict['isEnumObjectArray'] = True elif isinstance(_method.returnType.containedTypeDesc, AbsApi.ClassType): methodDict['isRealObjectArray'] = True methodDict['needLjb'] = True @@ -393,7 +409,8 @@ class JavaTranslator: elif isinstance(arg.type, AbsApi.ListType): isStringList = type(arg.type.containedTypeDesc) is AbsApi.BaseType and arg.type.containedTypeDesc.name == 'string' isObjList = type(arg.type.containedTypeDesc) is AbsApi.ClassType - methodDict['lists'].append({'list': argname, 'isStringList': isStringList, 'isObjList': isObjList, 'objectClassCName': arg.type.containedTypeDesc.name}) + isEnumList = type(arg.type.containedTypeDesc) is AbsApi.EnumType + methodDict['lists'].append({'list': argname, 'isStringList': isStringList, 'isEnumList': isEnumList, 'isObjList': isObjList, 'objectClassCName': arg.type.containedTypeDesc.name}) methodDict['params_impl'] += 'bctbx_list_' + argname elif isinstance(arg.type, AbsApi.EnumType): diff --git a/wrappers/java/java_class.mustache b/wrappers/java/java_class.mustache index f37c171de8..00afc705eb 100644 --- a/wrappers/java/java_class.mustache +++ b/wrappers/java/java_class.mustache @@ -273,7 +273,7 @@ class {{classImplName}} {{#isLinphoneFactory}}extends{{/isLinphoneFactory}}{{#is } } }{{/cantBeCalledIfObjectIsConst}} - {{#exception}}int exceptionResult = {{/exception}}{{return_keyword}}{{#enumCast}}{{return}}.fromInt({{/enumCast}}{{#classCast}}({{return}}){{/classCast}}{{name_native}}({{native_params_impl}}){{#enumCast}}){{/enumCast}};{{#exception}} + {{#exception}}int exceptionResult = {{/exception}}{{return_keyword}}{{#enumCast}}{{return}}.fromInt({{/enumCast}}{{#enumArrayCast}}{{enumName}}.fromIntArray({{/enumArrayCast}}{{#classCast}}({{return}}){{/classCast}}{{name_native}}({{native_params_impl}}){{#enumCast}}){{/enumCast}}{{#enumArrayCast}}){{/enumArrayCast}};{{#exception}} if (exceptionResult != 0) throw new CoreException("{{name}} returned value " + exceptionResult);{{/exception}}{{#hasCoreAccessor}}{{#isNotGetCore}} }{{/isNotGetCore}}{{/hasCoreAccessor}} } diff --git a/wrappers/java/java_enum.mustache b/wrappers/java/java_enum.mustache index a64299797e..2d1ee504e4 100644 --- a/wrappers/java/java_enum.mustache +++ b/wrappers/java/java_enum.mustache @@ -71,6 +71,24 @@ public enum {{{className}}} { throw new RuntimeException("Unhandled enum value " + value + " for {{className}}"); } } + + static protected {{className}}[] fromIntArray(int[] values) throws RuntimeException { + int arraySize = values.length; + {{className}}[] enumArray = new {{className}}[arraySize]; + for (int i = 0; i < arraySize; i++) { + enumArray[i] = {{className}}.fromInt(values[i]); + } + return enumArray; + } + + static protected int[] toIntArray({{className}}[] values) throws RuntimeException { + int arraySize = values.length; + int[] intArray = new int[arraySize]; + for (int i = 0; i < arraySize; i++) { + intArray[i] = values[i].toInt(); + } + return intArray; + } public int toInt() { return mValue; diff --git a/wrappers/java/jni.mustache b/wrappers/java/jni.mustache index afba1d0ec2..0084fab244 100644 --- a/wrappers/java/jni.mustache +++ b/wrappers/java/jni.mustache @@ -555,6 +555,7 @@ JNIEXPORT {{return}} JNICALL {{name}}({{params}}) { LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get()); jobjectArray jni_list_result = env->NewObjectArray(0, ljb->{{objectCPrefix}}_class, NULL);{{/isRealObjectArray}} {{#isStringObjectArray}}jobjectArray jni_list_result = env->NewObjectArray(0, env->FindClass("java/lang/String"), env->NewStringUTF(""));{{/isStringObjectArray}} + {{#isEnumObjectArray}}jintArray jni_list_result = env->NewIntArray(0);{{/isEnumObjectArray}} {{/hasListReturn}} return {{#hasReturn}}0{{/hasReturn}}{{#hasListReturn}}jni_list_result{{/hasListReturn}}{{#hasByteArrayReturn}}0{{/hasByteArrayReturn}}; } @@ -568,6 +569,7 @@ JNIEXPORT {{return}} JNICALL {{name}}({{params}}) { {{/objects}}{{#lists}} bctbx_list_t *bctbx_list_{{list}} = nullptr; int {{list}}_count = env->GetArrayLength({{list}}); + {{#isEnumList}}jint *int_elems_{{list}} = env->GetIntArrayElements({{list}}, 0);{{/isEnumList}} for (int i=0; i < {{list}}_count; i++) { {{#isStringList}} jstring obj = (jstring) env->GetObjectArrayElement({{list}}, i); @@ -581,6 +583,9 @@ JNIEXPORT {{return}} JNICALL {{name}}({{params}}) { jobject obj = env->GetObjectArrayElement({{list}}, i); bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, ({{objectClassCName}} *)GetObjectNativePtr(env, obj)); {{/isObjList}} + {{#isEnumList}} + bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, (void*)(intptr_t)int_elems_{{list}}[i]); + {{/isEnumList}} } {{/lists}}{{#hasListReturn}} {{#isConst}}const {{/isConst}}bctbx_list_t *list = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}); @@ -590,21 +595,32 @@ JNIEXPORT {{return}} JNICALL {{name}}({{params}}) { LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get()); jobjectArray jni_list_result = env->NewObjectArray((int)count, ljb->{{objectCPrefix}}_class, nullptr);{{/isRealObjectArray}} {{#isStringObjectArray}}jobjectArray jni_list_result = env->NewObjectArray((int)count, env->FindClass("java/lang/String"), env->NewStringUTF(""));{{/isStringObjectArray}} + {{#isEnumObjectArray}}jintArray jni_list_result = env->NewIntArray((int)count); + int carray[(int)count];{{/isEnumObjectArray}} int i = 0; while (list_it != nullptr) { {{#isRealObjectArray}} {{objectClassCName}}* c_object = ({{objectClassCName}}*)list_it->data; jobject object = get{{objectClassName}}(env, c_object, {{takeRefOnReturnedObject}}, {{isRealObjectConst}}); + if (object != nullptr) { + env->SetObjectArrayElement(jni_list_result, (int)i, object); + env->DeleteLocalRef(object); + } {{/isRealObjectArray}} {{#isStringObjectArray}}const char *cstring = (const char *)list_it->data; - jstring object = cstring ? get_jstring_from_char(env, cstring) : 0;{{/isStringObjectArray}} + jstring object = cstring ? get_jstring_from_char(env, cstring) : 0; if (object != nullptr) { env->SetObjectArrayElement(jni_list_result, (int)i, object); - {{#isRealObjectArray}}env->DeleteLocalRef(object);{{/isRealObjectArray}} - } + }{{/isStringObjectArray}} + {{#isEnumObjectArray}} + carray[i] = (int)(intptr_t)list_it->data; + {{/isEnumObjectArray}} list_it = bctbx_list_next(list_it); i += 1; } + {{#isEnumObjectArray}} + env->SetIntArrayRegion(jni_list_result, 0, (int)count, carray); + {{/isEnumObjectArray}} {{#isNotConst}}bctbx_list_free(list);{{/isNotConst}} {{/hasListReturn}}{{#hasByteArrayReturn}} {{c_type_return}} jni_result = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}); -- GitLab