[Kotlin] Generalize JNI signature logic.
There's going to be a third client for this in the
C -> Kotlin structure converters.
Change-Id: I36f50523f9ebd08500b4b997e7b1add404d53ea5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/197994
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Jim Blackler <jimblackler@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/templates/art/api_jni_types.kt b/generator/templates/art/api_jni_types.kt
index 7525672..2af0259 100644
--- a/generator/templates/art/api_jni_types.kt
+++ b/generator/templates/art/api_jni_types.kt
@@ -52,3 +52,35 @@
{{ jni_primitives[type.name.get()] }}
{% endif %}
{% endmacro %}
+
+{% macro jni_signature(member) %}
+ {%- if member.length == 'strlen' -%}
+ Ljava/lang/String;
+ {%- elif member.length and member.length != 'constant' -%}
+ {%- if member.type.category in ['bitmask', 'enum', 'function pointer', 'object', 'structure'] -%}
+ //* JvmInline does not inline bitmask/enums in arrays.
+ [L{{ jni_name(member.type) }};
+ {%- elif member.type.name.get() == 'uint32_t' -%}
+ [I
+ {%- else -%}
+ {{ unreachable_code() }}
+ {%- endif -%}
+ {%- elif member.type.category in ['function pointer', 'object', 'structure'] -%}
+ L{{ jni_name(member.type) }};
+ {%- elif member.type.name.get() in ['int', 'int64_t', 'uint64_t', 'size_t', 'void'] -%} {# remove void #}
+ J
+ {%- elif member.type.name.get() in ['int', 'int32_t', 'uint32_t'] or member.type.category in ['bitmask', 'enum'] -%}
+ //* JvmInline makes lone bitmask/enums appear as integer to JNI.
+ I
+ {%- elif member.type.name.get() in ['int16_t', 'uint16_t'] -%}
+ S
+ {%- elif member.type.name.get() == 'double' -%}
+ D
+ {%- elif member.type.name.get() == 'float' -%}
+ F
+ {%- elif member.type.name.get() == 'bool' -%}
+ Z
+ {%- else -%}
+ {{ unreachable_code() }}
+ {%- endif -%}
+{% endmacro %}
diff --git a/generator/templates/art/methods.cpp b/generator/templates/art/methods.cpp
index c5493ee..1ec546f 100644
--- a/generator/templates/art/methods.cpp
+++ b/generator/templates/art/methods.cpp
@@ -24,7 +24,7 @@
//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-{% from 'art/api_jni_types.kt' import arg_to_jni_type, to_jni_type with context %}
+{% from 'art/api_jni_types.kt' import arg_to_jni_type, jni_signature, to_jni_type with context %}
#include <jni.h>
#include <stdlib.h>
#include "dawn/webgpu.h"
@@ -182,15 +182,7 @@
jmethodID callbackMethod = env->GetMethodID(
env->FindClass("{{ jni_name(arg.type) }}"), "callback", "(
{%- for callbackArg in filter_arguments(arg.type.arguments) -%}
- {%- if callbackArg.type.category in ['bitmask', 'enum'] -%}
- I
- {%- elif callbackArg.type.category in ['object', 'structure'] -%}
- L{{ jni_name(callbackArg.type) }};
- {%- elif callbackArg.type.name.get() == 'char' -%}
- Ljava/lang/String;
- {%- else -%}
- {{ unreachable_code() }}
- {%- endif -%}
+ {{- jni_signature(callbackArg) -}}
{%- endfor %})V");
//* Call the callback with all converted parameters.
diff --git a/generator/templates/art/structures.cpp b/generator/templates/art/structures.cpp
index bfb14db..52e476f 100644
--- a/generator/templates/art/structures.cpp
+++ b/generator/templates/art/structures.cpp
@@ -24,6 +24,8 @@
//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+{% from 'art/api_jni_types.kt' import jni_signature with context %}
+
#include <jni.h>
#include "dawn/webgpu.h"
#include "structures.h"
@@ -39,23 +41,20 @@
//* Convert each member in turn from corresponding members of the Kotlin object obtained via
//* JNI calls
- {% for member in structure.members if include_structure_member(structure, member) %}
- {% if member.length == 'strlen' %} {
- jobject mObj = env->CallObjectMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}",
- "()Ljava/lang/String;"));
+ {% for member in structure.members if include_structure_member(structure, member) %} {
+ jmethodID method = env->GetMethodID(
+ clz, "get{{ member.name.CamelCase() }}", "(){{ jni_signature(member) }}");
+ {% if member.length == 'strlen' %}
+ jobject mObj = env->CallObjectMethod(obj, method);
if (mObj) {
//* TODO(b/330293719): free associated resources.
converted->{{ member.name.camelCase() }} =
env->GetStringUTFChars(reinterpret_cast<jstring>(mObj), 0);
}
- }
- {% elif member.constant_length == 1 %} {
+ {% elif member.constant_length == 1 %}
{% if member.type.category == 'structure' %}
//* Convert optional structure if present.
- jobject mObj = env->CallObjectMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}",
- "()L{{ jni_name(member.type) }};"));
+ jobject mObj = env->CallObjectMethod(obj, method);
if (mObj) {
//* TODO(b/330293719): free associated resources.
auto convertedMember = new {{ as_cType(member.type.name) }}();
@@ -63,13 +62,11 @@
converted->{{ member.name.camelCase() }} = convertedMember;
}
{% elif member.type.name.get() == 'void' %}
- converted->{{ member.name.camelCase() }} = reinterpret_cast<void*>(
- env->CallLongMethod(obj, env->GetMethodID(
- clz, "get{{ member.name.CamelCase() }}", "()J")));
+ converted->{{ member.name.camelCase() }} =
+ reinterpret_cast<void*>(env->CallLongMethod(obj, method));
{% else %}
{{ unreachable_code() }}
{% endif %}
- }
{% elif member.length %}
{% if member.constant_length %}
@@ -78,8 +75,7 @@
//* Convert container, including the length field.
{% if member.type.name.get() == 'uint32_t' %} {
//* This container type is represented in Kotlin as a primitive array.
- jintArray array = static_cast<jintArray>(env->CallObjectMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()[I")));
+ jintArray array = static_cast<jintArray>(env->CallObjectMethod(obj, method));
//* TODO(b/330293719): free associated resources.
converted->{{ member.name.camelCase() }} =
reinterpret_cast<{{ as_cType(member.type.name) }}*>(
@@ -88,9 +84,7 @@
}
{% else %} {
//* These container types are represented in Kotlin as arrays of objects.
- jmethodID getMethod = env->GetMethodID(clz,
- "get{{ member.name.CamelCase() }}", "()[L{{ jni_name(member.type) }};");
- auto in = static_cast<jobjectArray>(env->CallObjectMethod(obj, getMethod));
+ auto in = static_cast<jobjectArray>(env->CallObjectMethod(obj, method));
size_t length = env->GetArrayLength(in);
//* TODO(b/330293719): free associated resources.
auto out = new {{ as_cType(member.type.name) }}[length]();
@@ -125,9 +119,8 @@
{% endif %}
//* From here members are single values.
- {% elif member.type.category == 'object' %} {
- jobject mObj = env->CallObjectMethod(obj, env->GetMethodID(clz,
- "get{{ member.name.CamelCase() }}", "()L{{ jni_name(member.type) }};"));
+ {% elif member.type.category == 'object' %}
+ jobject mObj = env->CallObjectMethod(obj, method);
if (mObj) {
jclass memberClass = env->FindClass("{{ jni_name(member.type) }}");
jmethodID getHandle = env->GetMethodID(memberClass, "getHandle", "()J");
@@ -135,39 +128,33 @@
reinterpret_cast<{{ as_cType(member.type.name) }}>(
env->CallLongMethod(mObj, getHandle));
}
- }
- {% elif member.type.category == 'structure' or member.type.category == 'callback info' %}
- //* Mandatory structure.
- Convert(env, env->CallObjectMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}",
- "()L{{ jni_name(member.type) }};")),
- &converted->{{ member.name.camelCase() }});
- {% elif member.type.name.get() == 'bool' %}
- converted->{{ member.name.camelCase() }} = env->CallBooleanMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()Z"));
- {% elif member.type.name.get() == 'uint16_t' %}
- converted->{{ member.name.camelCase() }} =
- static_cast<{{ as_cType(member.type.name) }}>(env->CallShortMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()S")));
- {% elif member.type.name.get() in ['int', 'int32_t', 'uint32_t']
- or member.type.category in ['bitmask', 'enum'] %}
- converted->{{ member.name.camelCase() }} =
- static_cast<{{ as_cType(member.type.name) }}>(env->CallIntMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()I")));
- {% elif member.type.name.get() == 'float' %}
- converted->{{ member.name.camelCase() }} = env->CallFloatMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()F"));
- {% elif member.type.name.get() in ['size_t', 'uint64_t'] %}
- converted->{{ member.name.camelCase() }} =
- static_cast<{{ as_cType(member.type.name) }}>(env->CallLongMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()J")));
- {% elif member.type.name.get() == 'double' %}
- converted->{{ member.name.camelCase() }} = env->CallDoubleMethod(obj,
- env->GetMethodID(clz, "get{{ member.name.CamelCase() }}", "()D"));
{% else %}
- {{ unreachable_code() }}
+ {% if member.type.category == 'structure' or member.type.category == 'callback info' %}
+ //* Mandatory structure.
+ Convert(env, env->CallObjectMethod(obj, method),
+ &converted->{{ member.name.camelCase() }});
+ {% else %}
+ converted->{{ member.name.camelCase() }} =
+ static_cast<{{ as_cType(member.type.name) }}>(env->
+ {% if member.type.name.get() == 'bool' %}
+ CallBooleanMethod
+ {% elif member.type.name.get() == 'uint16_t' %}
+ CallShortMethod
+ {% elif member.type.name.get() in ['int', 'int32_t', 'uint32_t']
+ or member.type.category in ['bitmask', 'enum'] %}
+ CallIntMethod
+ {% elif member.type.name.get() == 'float' %}
+ CallFloatMethod
+ {% elif member.type.name.get() in ['size_t', 'uint64_t'] %}
+ CallLongMethod
+ {% elif member.type.name.get() == 'double' %}
+ CallDoubleMethod
+ {% else %}
+ {{ unreachable_code() }}
+ {% endif %} (obj, method));
+ {% endif %}
{% endif %}
- {% endfor %}
+ } {% endfor %}
//* Set up the chain type and links for child objects.
{% if structure.chained %}