From ed76d5f2e383834d8c6aae8ab3b89cf7d2479d0c Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Fri, 12 May 2017 18:24:34 +0200 Subject: jvpp: fix memory allocation for variable lenght messages (VPP-841) Change-Id: I9a46125e3cf9815c08cf8cca17713ec6e9121eae Signed-off-by: Marek Gradzki (cherry picked from commit 307cfd8eb14ff7df04316ffa56f2c2481d650d7e) --- src/vpp-api/java/jvpp/gen/jvpp_gen.py | 14 +++++++++----- src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py | 22 +++++++++++++++------- src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py | 23 ++++++++++++++++++----- src/vpp-api/java/jvpp/gen/jvppgen/types_gen.py | 12 +++++++----- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/vpp-api/java/jvpp/gen/jvpp_gen.py b/src/vpp-api/java/jvpp/gen/jvpp_gen.py index 2a5ada98..7932741d 100755 --- a/src/vpp-api/java/jvpp/gen/jvpp_gen.py +++ b/src/vpp-api/java/jvpp/gen/jvpp_gen.py @@ -96,14 +96,16 @@ def is_response_field(field_name): def get_args(t, filter): - arg_list = [] + arg_names = [] + arg_types = [] for i in t: if is_crc(i): continue if not filter(i[1]): continue - arg_list.append(i[1]) - return arg_list + arg_types.append(i[0]) + arg_names.append(i[1]) + return arg_types, arg_names def get_types(t, filter): @@ -143,16 +145,18 @@ def get_definitions(defs): # For replies include all the arguments except message_id if util.is_reply(java_name): types, lengths, crc = get_types(a[1:], is_response_field) + args = get_args(a[1:], is_response_field) func_name[a[0]] = dict( [('name', a[0]), ('java_name', java_name), - ('args', get_args(a[1:], is_response_field)), ('full_args', get_args(a[1:], lambda x: True)), + ('args', args[1]), ('arg_types', args[0]), ('types', types), ('lengths', lengths), crc]) # For requests skip message_id, client_id and context else: types, lengths, crc = get_types(a[1:], is_request_field) + args = get_args(a[1:], is_request_field) func_name[a[0]] = dict( [('name', a[0]), ('java_name', java_name), - ('args', get_args(a[1:], is_request_field)), ('full_args', get_args(a[1:], lambda x: True)), + ('args', args[1]), ('arg_types', args[0]), ('types', types), ('lengths', lengths), crc]) # Indexed by name diff --git a/src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py b/src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py index 328cc8d3..cb0d66e8 100644 --- a/src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py +++ b/src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py @@ -248,16 +248,13 @@ struct_setter_templates = {'u8': u8_struct_setter_template, } -def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_name, field_length, - is_variable_len_array, object_name="request"): +def jni_request_identifiers_for_type(field_type, field_reference_name, field_name, object_name="request"): """ - Generates jni code that initializes C structure that corresponds to a field of java object + Generates jni code that defines C variable corresponding to field of java object (dto or custom type). To be used in request message handlers. :param field_type: type of the field to be initialized (as defined in vpe.api) - :param c_name: name of the message struct member to be initialized :param field_reference_name: name of the field reference in generated code :param field_name: name of the field (camelcase) - :param field_length: integer or name of variable that stores field length :param object_name: name of the object to be initialized """ # field identifiers @@ -266,7 +263,7 @@ def jni_request_binding_for_type(field_type, c_name, field_reference_name, field jni_getter = util.jni_field_accessors[field_type] # field identifier - msg_initialization = request_field_identifier_template.substitute( + return request_field_identifier_template.substitute( jni_type=jni_type, field_reference_name=field_reference_name, field_name=field_name, @@ -274,6 +271,17 @@ def jni_request_binding_for_type(field_type, c_name, field_reference_name, field jni_getter=jni_getter, object_name=object_name) + +def jni_request_binding_for_type(field_type, c_name, field_reference_name, field_length, is_variable_len_array): + """ + Generates jni code that initializes C structure that corresponds to a field of java object + (dto or custom type). To be used in request message handlers. + :param field_type: type of the field to be initialized (as defined in vpe.api) + :param c_name: name of the message struct member to be initialized + :param field_reference_name: name of the field reference in generated code + :param field_length: integer or name of variable that stores field length + """ + # field setter field_length_check = "" @@ -287,7 +295,7 @@ def jni_request_binding_for_type(field_type, c_name, field_reference_name, field struct_setter_template = struct_setter_templates[field_type] - msg_initialization += struct_setter_template.substitute( + msg_initialization = struct_setter_template.substitute( c_name=c_name, field_reference_name=field_reference_name, field_length_check=field_length_check) diff --git a/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py b/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py index 5b0fbc95..1425cdb7 100644 --- a/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py +++ b/src/vpp-api/java/jvpp/gen/jvppgen/jvpp_c_gen.py @@ -113,6 +113,7 @@ request_field_identifier_template = Template(""" ${jni_type} ${field_reference_name} = (*env)->Get${jni_getter}(env, ${object_name}, ${field_reference_name}FieldId); """) +jni_msg_size_template = Template(""" + ${array_length}*sizeof(${element_type})""") jni_impl_template = Template(""" /** @@ -127,9 +128,11 @@ JNIEXPORT jint JNICALL Java_io_fd_vpp_jvpp_${plugin_name}_JVpp${java_plugin_name u32 my_context_id = vppjni_get_context_id (&jvpp_main); $request_class + $jni_identifiers + // create message: - mp = vl_msg_api_alloc(sizeof(*mp)); - memset (mp, 0, sizeof (*mp)); + mp = vl_msg_api_alloc(${msg_size}); + memset (mp, 0, ${msg_size}); mp->_vl_msg_id = ntohs (get_message_id(env, "${c_name}_${crc}")); mp->client_index = plugin_main->my_client_index; mp->context = clib_host_to_net_u32 (my_context_id); @@ -155,8 +158,10 @@ def generate_jni_impl(func_list, plugin_name, inputfile): arguments = '' request_class = '' + jni_identifiers = '' msg_initialization = '' f_name_uppercase = f_name.upper() + msg_size = 'sizeof(*mp)' if f['args']: arguments = ', jobject request' @@ -166,13 +171,19 @@ def generate_jni_impl(func_list, plugin_name, inputfile): java_name_upper=camel_case_function_name_upper, plugin_name=plugin_name) - for t in zip(f['types'], f['args'], f['lengths']): + for t in zip(f['types'], f['args'], f['lengths'], f['arg_types']): field_name = util.underscore_to_camelcase(t[1]) + is_variable_len_array = t[2][1] + if is_variable_len_array: + msg_size += jni_msg_size_template.substitute(array_length=util.underscore_to_camelcase(t[2][0]), + element_type=t[3]) + jni_identifiers += jni_gen.jni_request_identifiers_for_type(field_type=t[0], + field_reference_name=field_name, + field_name=field_name) msg_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=t[1], field_reference_name=field_name, - field_name=field_name, field_length=t[2][0], - is_variable_len_array=t[2][1]) + is_variable_len_array=is_variable_len_array) jni_impl.append(jni_impl_template.substitute( inputfile=inputfile, @@ -185,6 +196,8 @@ def generate_jni_impl(func_list, plugin_name, inputfile): plugin_name=plugin_name, java_plugin_name=plugin_name.title(), request_class=request_class, + jni_identifiers=jni_identifiers, + msg_size=msg_size, msg_initialization=msg_initialization, args=arguments)) diff --git a/src/vpp-api/java/jvpp/gen/jvppgen/types_gen.py b/src/vpp-api/java/jvpp/gen/jvppgen/types_gen.py index 7a5eec37..93883ba1 100644 --- a/src/vpp-api/java/jvpp/gen/jvppgen/types_gen.py +++ b/src/vpp-api/java/jvpp/gen/jvppgen/types_gen.py @@ -108,12 +108,14 @@ def generate_struct_initialization(type_def, c_name_prefix, object_name, indent) for t in zip(type_def['types'], type_def['args'], type_def['lengths']): field_reference_name = "${c_name}" + util.underscore_to_camelcase_upper(t[1]) field_name = util.underscore_to_camelcase(t[1]) + struct_initialization += jni_gen.jni_request_identifiers_for_type(field_type=t[0], + field_reference_name=field_reference_name, + field_name=field_name, + object_name=object_name) struct_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=c_name_prefix + t[1], - field_reference_name=field_reference_name, - field_name=field_name, - field_length=t[2][0], - is_variable_len_array=t[2][1], - object_name=object_name) + field_reference_name=field_reference_name, + field_length=t[2][0], + is_variable_len_array=t[2][1]) return indent + struct_initialization.replace('\n', '\n' + indent) -- cgit 1.2.3-korg