jvpp: cleanup JNI generation code (VPP-1153) 53/13153/2
authorMarek Gradzki <mgradzki@cisco.com>
Wed, 20 Jun 2018 11:15:08 +0000 (13:15 +0200)
committerOle Trøan <otroan@employees.org>
Fri, 22 Jun 2018 07:03:06 +0000 (07:03 +0000)
Minor cleanup that includes unifying
common Java to C and C to Java translation code.

Change-Id: I14d63dbe06334c3bbfbde75043de04d2c08f3dfd
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
src/vpp-api/java/jvpp/gen/jvppgen/jni_common_gen.py
src/vpp-api/java/jvpp/gen/jvppgen/jni_gen.py
src/vpp-api/java/jvpp/gen/jvppgen/jni_type_handlers_gen.py

index 6f2995d..3b9969c 100755 (executable)
@@ -15,7 +15,7 @@
 #
 from string import Template
 
-from jvpp_model import is_array, Class, is_retval
+from jvpp_model import is_array, is_retval, Class
 
 
 def generate_j2c_identifiers(element, class_ref_name, object_ref_name):
@@ -38,58 +38,71 @@ _REQUEST_FIELD_IDENTIFIER_TEMPLATE = Template("""
 """)
 
 
-# TODO(VPP-1185): introduce host_to_net functions wrappers and simplify j2c and c2j swap generation
+# TODO(VPP-1187): do not inline JNI object creation inside message handlers to reduce number of special cases
 def generate_j2c_swap(element, struct_ref_name):
     initialization = []
     for field in element.fields:
-        field_type = field.type
         if is_array(field):
-            template = _ARRAY_J2C_NO_SWAP_TEMPLATE
-            field_reference_name = field.java_name
-            c_name = field.name
-            swap_elements = None
-            jni_name = None
-            if field_type.is_swap_needed:
-                template = _ARRAY_J2C_SWAP_TEMPLATE
-                host = "%sArrayElements[_i]" % field_reference_name
-                net = "%s->%s[_i]" % (struct_ref_name, c_name)
-                swap_elements = field_type.get_host_to_net_function(host, net)
-            if isinstance(field_type.base_type, Class):
-                jni_name = field_type.base_type.jni_name
-                host = "%sArrayElement" % field_reference_name
-                net = "%s->%s[_i]" % (struct_ref_name, c_name)
-                swap_elements = field_type.get_host_to_net_function(host, net)
-                template = _CLASS_ARRAY_J2C_TEMPLATE
-
-            initialization.append(template.substitute(
-                field_reference_name=field_reference_name,
-                field_length_check=_generate_field_length_check(field),
-                base_type=field_type.base_type.jni_accessor,
-                jni_base_type=field_type.base_type.jni_type,
-                struct_reference_name=struct_ref_name,
-                jni_name=jni_name,
-                c_name=c_name,
-                swap_elements=swap_elements
-            ))
+            initialization.append(_generate_j2c_array_swap(field, struct_ref_name))
         else:
-            if field_type.is_swap_needed:
-                host = field.java_name
-                net = "%s->%s" % (struct_ref_name, field.name)
-                initialization.append("    %s;" % field_type.get_host_to_net_function(host, net))
-            else:
-                initialization.append("    %s->%s = %s;" % (struct_ref_name, field.name, field.java_name))
+            initialization.append(_generate_j2c_scalar_swap(field, struct_ref_name))
 
     return "\n".join(initialization)
 
-_ARRAY_J2C_NO_SWAP_TEMPLATE = Template("""
-    if (${field_reference_name}) {
-        jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
-        ${field_length_check}
-        (*env)->Get${base_type}ArrayRegion(env, ${field_reference_name}, 0, cnt, (${jni_base_type} *)${struct_reference_name}->${c_name});
+
+def _generate_j2c_array_swap(field, struct_ref_name):
+    # TODO(VPP-1186): move the logic to JNI generators
+    base_type = field.type.base_type
+    if isinstance(base_type, Class):
+        return _generate_j2c_object_array_swap(field, struct_ref_name)
+    elif base_type.is_swap_needed:
+        return _generate_j2c_primitive_type_array_swap(field, struct_ref_name)
+    else:
+        return _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name)
+
+
+def _generate_j2c_object_array_swap(field, struct_ref_name):
+    field_type = field.type
+    field_reference_name = field.java_name
+    c_name = field.name
+    host = "%sArrayElement" % field_reference_name
+    net = "%s->%s[_i]" % (struct_ref_name, c_name)
+    swap_elements = field_type.get_host_to_net_function(host, net)
+    return _J2C_OBJECT_ARRAY_SWAP_TEMPLATE.substitute(
+        field_reference_name=field_reference_name,
+        field_length_check=_generate_field_length_check(field),
+        swap_elements=swap_elements)
+
+_J2C_OBJECT_ARRAY_SWAP_TEMPLATE = Template("""
+    {
+        if (${field_reference_name}) {
+            size_t _i;
+            jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+            ${field_length_check}
+            for (_i = 0; _i < cnt; _i++) {
+                jobject ${field_reference_name}ArrayElement = (*env)->GetObjectArrayElement(env, ${field_reference_name}, _i);
+                ${swap_elements};
+            }
+        }
     }
 """)
 
-_ARRAY_J2C_SWAP_TEMPLATE = Template("""
+
+def _generate_j2c_primitive_type_array_swap(field, struct_ref_name):
+    field_reference_name = field.java_name
+    field_type = field.type
+    host = "%sArrayElements[_i]" % field_reference_name
+    net = "%s->%s[_i]" % (struct_ref_name,  field.name)
+    swap_elements = field_type.get_host_to_net_function(host, net)
+    return _J2C_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE.substitute(
+        field_reference_name=field_reference_name,
+        field_length_check=_generate_field_length_check(field),
+        base_type=field_type.base_type.jni_accessor,
+        jni_base_type=field_type.base_type.jni_type,
+        swap_elements=swap_elements
+    )
+
+_J2C_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE = Template("""
     if (${field_reference_name}) {
         ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
         size_t _i;
@@ -102,17 +115,23 @@ _ARRAY_J2C_SWAP_TEMPLATE = Template("""
     }
     """)
 
-_CLASS_ARRAY_J2C_TEMPLATE = Template("""
-    {
-        if (${field_reference_name}) {
-            size_t _i;
-            jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
-            ${field_length_check}
-            for (_i = 0; _i < cnt; _i++) {
-                jobject ${field_reference_name}ArrayElement = (*env)->GetObjectArrayElement(env, ${field_reference_name}, _i);
-                ${swap_elements};
-            }
-        }
+
+def _generate_j2c_primitive_type_array_no_swap(field, struct_ref_name):
+    field_type = field.type
+    return _J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE.substitute(
+        field_reference_name=field.java_name,
+        field_length_check=_generate_field_length_check(field),
+        base_type=field_type.base_type.jni_accessor,
+        jni_base_type=field_type.base_type.jni_type,
+        struct_reference_name=struct_ref_name,
+        c_name=field.name
+    )
+
+_J2C_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template("""
+    if (${field_reference_name}) {
+        jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
+        ${field_length_check}
+        (*env)->Get${base_type}ArrayRegion(env, ${field_reference_name}, 0, cnt, (${jni_base_type} *)${struct_reference_name}->${c_name});
     }
 """)
 
@@ -135,128 +154,131 @@ _FIELD_LENGTH_CHECK = Template("""
         if (cnt > max_size) cnt = max_size;""")
 
 
+def _generate_j2c_scalar_swap(field, struct_ref_name):
+    field_type = field.type
+    if field_type.is_swap_needed:
+        host = field.java_name
+        net = "%s->%s" % (struct_ref_name, field.name)
+        return "    %s;" % field_type.get_host_to_net_function(host, net)
+    else:
+        return "    %s->%s = %s;" % (struct_ref_name, field.name, field.java_name)
+
+
 def generate_c2j_swap(element, object_ref_name, struct_ref_name):
     msg_java_name = element.java_name_lower
-    setters = []
+    initialization = []
     for field in element.fields:
-        field_type = field.type
         if is_retval(field):
             # For retval don't generate setters and generate retval check
             continue
         elif is_array(field):
-            jni_name = ""
-            template = _ARRAY_C2J_SWAP_TEMPLATE if field_type.is_swap_needed else _ARRAY_C2J_NO_SWAP_TEMPLATE
-            if isinstance(field_type.base_type, Class):
-                template = _ARRAY_C2J_CLASS_SWAP_TEMPLATE
-                jni_name = field_type.base_type.jni_name
-            setters.append(template.substitute(
-                field_reference_name=field.java_name,
-                class_ref_name=msg_java_name,
-                jni_signature=field_type.jni_signature,
-                jni_type=field_type.jni_type,
-                jni_name=jni_name,
-                base_type=field_type.base_type.jni_accessor,
-                field_length=_generate_array_length(field, struct_ref_name),
-                jni_base_type=field_type.base_type.jni_type,
-                object_ref_name=object_ref_name,
-                struct_ref_name=struct_ref_name,
-                net_to_host_function=field_type.net_to_host_function,
-                c_name=field.name
-            ))
+            initialization.append(_generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name))
         else:
-            if field_type.is_swap_needed:
-                template = _SIMPLE_TYPE_FIELD_SETTER_TEMPLATE
-                jni_name = ""
-                if isinstance(field_type, Class):
-                    template = _STRUCT_SETTER_TEMPLATE
-                    jni_name = field_type.jni_name
-                setters.append(template.substitute(
-                    java_name=field.java_name,
-                    class_ref_name=msg_java_name,
-                    jni_signature=field_type.jni_signature,
-                    jni_name=jni_name,
-                    jni_accessor=field_type.jni_accessor,
-                    object_ref_name=object_ref_name,
-                    struct_ref_name=struct_ref_name,
-                    net_to_host_function=field_type.net_to_host_function,
-                    c_name=field.name
-                ))
-            else:
-                setters.append(_SIMPLE_TYPE_NO_SWAP_FIELD_SETTER_TEMPLATE.substitute(
-                    java_name=field.java_name,
-                    class_ref_name=msg_java_name,
-                    jni_signature=field_type.jni_signature,
-                    jni_accessor=field_type.jni_accessor,
-                    object_ref_name=object_ref_name,
-                    struct_ref_name=struct_ref_name,
-                    c_name=field.name
-                ))
-    return "".join(setters)
-
-
-_SIMPLE_TYPE_FIELD_SETTER_TEMPLATE = Template("""
-    jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
-    (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(${struct_ref_name}->${c_name}));
-""")
+            initialization.append(_generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name))
+    return "".join(initialization)
 
-_STRUCT_SETTER_TEMPLATE = Template("""
-    jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
-    jclass ${java_name}Class = (*env)->FindClass(env, "${jni_name}");
-    jmethodID ${java_name}Constructor = (*env)->GetMethodID(env, ${java_name}Class, "<init>", "()V");
-    jobject ${java_name} = (*env)->NewObject(env, ${java_name}Class,  ${java_name}Constructor);
-    ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}), ${java_name});
-    (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${java_name});
-    (*env)->DeleteLocalRef(env, ${java_name});
-""")
 
-_SIMPLE_TYPE_NO_SWAP_FIELD_SETTER_TEMPLATE = Template("""
-    jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
-    (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${struct_ref_name}->${c_name});
-""")
+def _generate_c2j_array_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    # TODO(VPP-1186): move the logic to JNI generators
+    base_type = field.type.base_type
+    if isinstance(base_type, Class):
+        return _generate_c2j_class_array_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+    elif base_type.is_swap_needed:
+        return _generate_c2j_primitive_type_array_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+    else:
+        return _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name)
 
-_ARRAY_C2J_NO_SWAP_TEMPLATE = Template("""
-    jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
-    ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
-    (*env)->Set${base_type}ArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const ${jni_base_type}*)${struct_ref_name}->${c_name});
-    (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
-    (*env)->DeleteLocalRef(env, ${field_reference_name});
-""")
 
-_ARRAY_C2J_SWAP_TEMPLATE = Template("""
+def _generate_c2j_class_array_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    return _C2J_CLASS_ARRAY_SWAP_TEMPLATE.substitute(
+        field_reference_name=field.java_name,
+        class_ref_name=msg_java_name,
+        jni_signature=field_type.jni_signature,
+        jni_name=field_type.base_type.jni_name,
+        field_length=_generate_array_length(field, struct_ref_name),
+        net_to_host_function=field_type.net_to_host_function,
+        struct_ref_name=struct_ref_name,
+        object_ref_name=object_ref_name,
+        c_name=field.name
+    )
+
+_C2J_CLASS_ARRAY_SWAP_TEMPLATE = Template("""
     jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
     {
-        ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
-        ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
+        jclass ${field_reference_name}Class = (*env)->FindClass(env, "${jni_name}");
+        jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0);
+        jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
         unsigned int _i;
         for (_i = 0; _i < ${field_length}; _i++) {
-            ${field_reference_name}ArrayElements[_i] = ${net_to_host_function}(${struct_ref_name}->${c_name}[_i]);
+            jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class,  ${field_reference_name}Constructor);
+            ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}[_i]), ${field_reference_name}ArrayElement);
+            (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement);
+            (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement);
         }
-
-        (*env)->Release${base_type}ArrayElements(env,  ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
         (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
         (*env)->DeleteLocalRef(env, ${field_reference_name});
     }
 """)
 
-_ARRAY_C2J_CLASS_SWAP_TEMPLATE = Template("""
+
+def _generate_c2j_primitive_type_array_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    return _C2J_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE.substitute(
+        field_reference_name=field.java_name,
+        class_ref_name=msg_java_name,
+        jni_signature=field_type.jni_signature,
+        jni_type=field_type.jni_type,
+        base_type=field_type.base_type.jni_accessor,
+        field_length=_generate_array_length(field, struct_ref_name),
+        jni_base_type=field_type.base_type.jni_type,
+        object_ref_name=object_ref_name,
+        struct_ref_name=struct_ref_name,
+        net_to_host_function=field_type.net_to_host_function,
+        c_name=field.name
+    )
+
+_C2J_PRIMITIVE_TYPE_ARRAY_SWAP_TEMPLATE = Template("""
     jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
     {
-        jclass ${field_reference_name}Class = (*env)->FindClass(env, "${jni_name}");
-        jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0);
-        jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
+        ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
+        ${jni_base_type} * ${field_reference_name}ArrayElements = (*env)->Get${base_type}ArrayElements(env, ${field_reference_name}, NULL);
         unsigned int _i;
         for (_i = 0; _i < ${field_length}; _i++) {
-            jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class,  ${field_reference_name}Constructor);
-            ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}[_i]), ${field_reference_name}ArrayElement);
-            (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement);
-            (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement);
+            ${field_reference_name}ArrayElements[_i] = ${net_to_host_function}(${struct_ref_name}->${c_name}[_i]);
         }
+
+        (*env)->Release${base_type}ArrayElements(env,  ${field_reference_name}, ${field_reference_name}ArrayElements, 0);
         (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
         (*env)->DeleteLocalRef(env, ${field_reference_name});
     }
 """)
 
 
+def _generate_c2j_primitive_type_array_no_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    return _C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE.substitute(
+        field_reference_name=field.java_name,
+        class_ref_name=msg_java_name,
+        jni_signature=field_type.jni_signature,
+        jni_type=field_type.jni_type,
+        base_type=field_type.base_type.jni_accessor,
+        field_length=_generate_array_length(field, struct_ref_name),
+        jni_base_type=field_type.base_type.jni_type,
+        object_ref_name=object_ref_name,
+        struct_ref_name=struct_ref_name,
+        c_name=field.name
+    )
+
+_C2J_PRIMITIVE_TYPE_ARRAY_NO_SWAP_TEMPLATE = Template("""
+    jfieldID ${field_reference_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${field_reference_name}", "${jni_signature}");
+    ${jni_type} ${field_reference_name} = (*env)->New${base_type}Array(env, ${field_length});
+    (*env)->Set${base_type}ArrayRegion(env, ${field_reference_name}, 0, ${field_length}, (const ${jni_base_type}*)${struct_ref_name}->${c_name});
+    (*env)->SetObjectField(env, ${object_ref_name}, ${field_reference_name}FieldId, ${field_reference_name});
+    (*env)->DeleteLocalRef(env, ${field_reference_name});
+""")
+
+
 def _generate_array_length(field, struct_ref_name):
     if field.array_len_field:
         len_field = field.array_len_field
@@ -265,3 +287,76 @@ def _generate_array_length(field, struct_ref_name):
         else:
             return "%s->%s" % (struct_ref_name, len_field.name)
     return field.array_len
+
+
+def _generate_c2j_scalar_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    if field_type.is_swap_needed:
+        # TODO(VPP-1186): move the logic to JNI generators
+        if isinstance(field_type, Class):
+            return _generate_c2j_class_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+        else:
+            return _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+    else:
+        return _generate_c2j_primitive_type_no_swap(msg_java_name, field, object_ref_name, struct_ref_name)
+
+
+def _generate_c2j_class_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    return _C2J_CLASS_SWAP_TEMPLATE.substitute(
+        java_name=field.java_name,
+        class_ref_name=msg_java_name,
+        jni_signature=field_type.jni_signature,
+        jni_name=field_type.jni_name,
+        jni_accessor=field_type.jni_accessor,
+        object_ref_name=object_ref_name,
+        struct_ref_name=struct_ref_name,
+        net_to_host_function=field_type.net_to_host_function,
+        c_name=field.name)
+
+_C2J_CLASS_SWAP_TEMPLATE = Template("""
+    jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
+    jclass ${java_name}Class = (*env)->FindClass(env, "${jni_name}");
+    jmethodID ${java_name}Constructor = (*env)->GetMethodID(env, ${java_name}Class, "<init>", "()V");
+    jobject ${java_name} = (*env)->NewObject(env, ${java_name}Class,  ${java_name}Constructor);
+    ${net_to_host_function}(env, &(${struct_ref_name}->${c_name}), ${java_name});
+    (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${java_name});
+    (*env)->DeleteLocalRef(env, ${java_name});
+""")
+
+
+def _generate_c2j_primitive_type_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    return _C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE.substitute(
+        java_name=field.java_name,
+        class_ref_name=msg_java_name,
+        jni_signature=field_type.jni_signature,
+        jni_accessor=field_type.jni_accessor,
+        object_ref_name=object_ref_name,
+        net_to_host_function=field_type.net_to_host_function,
+        struct_ref_name=struct_ref_name,
+        c_name=field.name
+    )
+
+_C2J_PRIMITIVE_TYPE_SWAP_TEMPLATE = Template("""
+    jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
+    (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${net_to_host_function}(${struct_ref_name}->${c_name}));
+""")
+
+
+def _generate_c2j_primitive_type_no_swap(msg_java_name, field, object_ref_name, struct_ref_name):
+    field_type = field.type
+    return _C2J_PRIMITIVE_TYPE_NO_SWAP_TEMPLATE.substitute(
+        java_name=field.java_name,
+        class_ref_name=msg_java_name,
+        jni_signature=field_type.jni_signature,
+        jni_accessor=field_type.jni_accessor,
+        object_ref_name=object_ref_name,
+        struct_ref_name=struct_ref_name,
+        c_name=field.name
+    )
+
+_C2J_PRIMITIVE_TYPE_NO_SWAP_TEMPLATE = Template("""
+    jfieldID ${java_name}FieldId = (*env)->GetFieldID(env, ${class_ref_name}Class, "${java_name}", "${jni_signature}");
+    (*env)->Set${jni_accessor}Field(env, ${object_ref_name}, ${java_name}FieldId, ${struct_ref_name}->${c_name});
+""")
index a20a90d..ad6c261 100755 (executable)
@@ -31,7 +31,7 @@ def generate_jni(work_dir, model, logger):
             json_filename=model.json_api_files,
             class_cache=_generate_class_cache(plugin_name, messages),
             api_verification=_generate_api_verification(messages),
-            type_handlers=generate_type_handlers(model),
+            type_handlers=generate_type_handlers(model, logger),
             jni_implementations=generate_jni_impl(model),
             msg_handlers=generate_jni_handlers(model),
             handler_registration=_generate_handler_registration(messages)))
index eb6ab23..c32acc1 100755 (executable)
@@ -19,39 +19,46 @@ from jni_common_gen import generate_j2c_swap, generate_j2c_identifiers, generate
 from jvpp_model import Class
 
 
-def generate_type_handlers(model):
+def generate_type_handlers(model, logger):
     """
-    Generates msg handlers for all messages except for dumps and requests (handled by vpp, not client).
+    Generates host-to-net and net-to-host functions for all custom types defined in the VPP API
     :param model: meta-model of VPP API used for jVPP generation.
+    :param logger: jVPP logger
     """
     type_handlers = []
     for t in model.types:
-        if not isinstance(t, Class):
-            continue
-        ref_name = t.java_name_lower
-        jni_identifiers = generate_j2c_identifiers(t, class_ref_name="%sClass" % ref_name, object_ref_name="_host")
-        type_handlers.append(_TYPE_NET_TO_HOST_TEMPLATE.substitute(
-            c_name=t.name,
-            json_filename=model.json_api_files,
-            json_definition=t.doc,
-            type_reference_name=ref_name,
-            class_FQN=t.jni_name,
-            jni_identifiers=jni_identifiers,
-            type_swap=generate_j2c_swap(t, struct_ref_name="_net")
-        ))
-
-        type_handlers.append(_TYPE_HOST_TO_NET_TEMPLATE.substitute(
-            c_name=t.name,
-            json_filename=model.json_api_files,
-            json_definition=t.doc,
-            type_reference_name=ref_name,
-            class_FQN=t.jni_name,
-            jni_identifiers=jni_identifiers,
-            type_swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net")
-        ))
+        #TODO(VPP-1186): move the logic to JNI generators
+        if isinstance(t, Class):
+            _generate_class(model, t, type_handlers)
+        else:
+            logger.debug("Skipping custom JNI type handler generation for %s", t)
 
     return "\n".join(type_handlers)
 
+
+def _generate_class(model, t, type_handlers):
+    ref_name = t.java_name_lower
+    jni_identifiers = generate_j2c_identifiers(t, class_ref_name="%sClass" % ref_name, object_ref_name="_host")
+    type_handlers.append(_TYPE_NET_TO_HOST_TEMPLATE.substitute(
+        c_name=t.name,
+        json_filename=model.json_api_files,
+        json_definition=t.doc,
+        type_reference_name=ref_name,
+        class_FQN=t.jni_name,
+        jni_identifiers=jni_identifiers,
+        type_swap=generate_j2c_swap(t, struct_ref_name="_net")
+    ))
+
+    type_handlers.append(_TYPE_HOST_TO_NET_TEMPLATE.substitute(
+        c_name=t.name,
+        json_filename=model.json_api_files,
+        json_definition=t.doc,
+        type_reference_name=ref_name,
+        class_FQN=t.jni_name,
+        jni_identifiers=jni_identifiers,
+        type_swap=generate_c2j_swap(t, object_ref_name="_host", struct_ref_name="_net")
+    ))
+
 _TYPE_NET_TO_HOST_TEMPLATE = Template("""
 /**
  * Host to network byte order conversion for ${c_name} type.
@@ -76,3 +83,19 @@ static inline void _net_to_host_${c_name}(JNIEnv * env, vl_api_${c_name}_t * _ne
     jclass ${type_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
 $type_swap
 }""")
+
+
+def _generate_scalar_host_to_net_swap(field):
+    field_type = field.type
+    if field_type.is_swap_needed:
+        return field_type.get_host_to_net_function(field.java_name, "*_net")
+    else:
+        return "*_net = %s" % field.java_name
+
+
+def _generate_scalar_net_to_host_swap(field):
+    field_type = field.type
+    if field_type.is_swap_needed:
+        return "%s((%s) _net);" % (field_type.net_to_host_function, field_type.name)
+    else:
+        return "_net"
\ No newline at end of file