Merge pull request #102817 from dsnopek/java-class-wrapper-array-improvements

JavaClassWrapper: Improve handling of typed array arguments
This commit is contained in:
Thaddeus Crews 2025-03-05 12:07:44 -06:00
commit 8ef0075193
No known key found for this signature in database
GPG Key ID: 62181B86FE9E5D84

View File

@ -132,6 +132,116 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
}
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_BOOLEAN: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::BOOL) {
arg_expected = Variant::ARRAY;
}
} else {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_BYTE:
case ARG_ARRAY_BIT | ARG_TYPE_CHAR: {
if (p_args[i]->get_type() != Variant::PACKED_BYTE_ARRAY) {
arg_expected = Variant::PACKED_BYTE_ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_SHORT:
case ARG_ARRAY_BIT | ARG_TYPE_INT: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::INT) {
arg_expected = Variant::ARRAY;
}
} else if (p_args[i]->get_type() != Variant::PACKED_INT32_ARRAY) {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_LONG: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::INT) {
arg_expected = Variant::ARRAY;
}
} else if (p_args[i]->get_type() != Variant::PACKED_INT64_ARRAY) {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_FLOAT: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::FLOAT) {
arg_expected = Variant::ARRAY;
}
} else if (p_args[i]->get_type() != Variant::PACKED_FLOAT32_ARRAY) {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_DOUBLE: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::FLOAT) {
arg_expected = Variant::ARRAY;
}
} else if (p_args[i]->get_type() != Variant::PACKED_FLOAT64_ARRAY) {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_STRING:
case ARG_ARRAY_BIT | ARG_TYPE_CHARSEQUENCE: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::STRING) {
arg_expected = Variant::ARRAY;
}
} else if (p_args[i]->get_type() != Variant::PACKED_STRING_ARRAY) {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_CALLABLE: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::CALLABLE) {
arg_expected = Variant::ARRAY;
}
} else {
arg_expected = Variant::ARRAY;
}
} break;
case ARG_ARRAY_BIT | ARG_TYPE_CLASS: {
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
if (arr.is_typed() && arr.get_typed_builtin() != Variant::OBJECT) {
arg_expected = Variant::ARRAY;
} else {
String cn = E.param_sigs[i].operator String();
if (cn.begins_with("[L") && cn.ends_with(";")) {
cn = cn.substr(2, cn.length() - 3);
}
jclass c = env->FindClass(cn.utf8().get_data());
if (c) {
for (int j = 0; j < arr.size(); j++) {
Ref<JavaObject> jo = arr[j];
if (jo.is_valid()) {
if (!env->IsInstanceOf(jo->instance, c)) {
arg_expected = Variant::ARRAY;
break;
}
} else {
arg_expected = Variant::ARRAY;
break;
}
}
} else {
arg_expected = Variant::ARRAY;
}
}
} else {
arg_expected = Variant::ARRAY;
}
} break;
default: {
if (p_args[i]->get_type() != Variant::ARRAY) {
arg_expected = Variant::ARRAY;
@ -307,90 +417,171 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
} break;
case ARG_ARRAY_BIT | ARG_TYPE_BYTE: {
Array arr = *p_args[i];
jbyteArray a = env->NewByteArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jbyte val = arr[j];
env->SetByteArrayRegion(a, j, 1, &val);
jbyteArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewByteArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jbyte val = arr[j];
env->SetByteArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_BYTE_ARRAY) {
PackedByteArray arr = *p_args[i];
a = env->NewByteArray(arr.size());
env->SetByteArrayRegion(a, 0, arr.size(), (const jbyte *)arr.ptr());
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_CHAR: {
Array arr = *p_args[i];
jcharArray a = env->NewCharArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jchar val = arr[j];
env->SetCharArrayRegion(a, j, 1, &val);
jcharArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewCharArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jchar val = arr[j];
env->SetCharArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_BYTE_ARRAY) {
PackedByteArray arr = *p_args[i];
// The data is expected to be UTF-16 encoded, so the length is half the size of the byte array.
int size = arr.size() / 2;
a = env->NewCharArray(size);
env->SetCharArrayRegion(a, 0, size, (const jchar *)arr.ptr());
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_SHORT: {
Array arr = *p_args[i];
jshortArray a = env->NewShortArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jshort val = arr[j];
env->SetShortArrayRegion(a, j, 1, &val);
jshortArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewShortArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jshort val = arr[j];
env->SetShortArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_INT32_ARRAY) {
PackedInt32Array arr = *p_args[i];
a = env->NewShortArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jshort val = arr[j];
env->SetShortArrayRegion(a, j, 1, &val);
}
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_INT: {
Array arr = *p_args[i];
jintArray a = env->NewIntArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jint val = arr[j];
env->SetIntArrayRegion(a, j, 1, &val);
jintArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewIntArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jint val = arr[j];
env->SetIntArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_INT32_ARRAY) {
PackedInt32Array arr = *p_args[i];
a = env->NewIntArray(arr.size());
env->SetIntArrayRegion(a, 0, arr.size(), arr.ptr());
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_LONG: {
Array arr = *p_args[i];
jlongArray a = env->NewLongArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jlong val = (int64_t)arr[j];
env->SetLongArrayRegion(a, j, 1, &val);
jlongArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewLongArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jlong val = (int64_t)arr[j];
env->SetLongArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_INT64_ARRAY) {
PackedInt64Array arr = *p_args[i];
a = env->NewLongArray(arr.size());
env->SetLongArrayRegion(a, 0, arr.size(), arr.ptr());
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_FLOAT: {
Array arr = *p_args[i];
jfloatArray a = env->NewFloatArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jfloat val = arr[j];
env->SetFloatArrayRegion(a, j, 1, &val);
jfloatArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewFloatArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jfloat val = arr[j];
env->SetFloatArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_FLOAT32_ARRAY) {
PackedFloat32Array arr = *p_args[i];
a = env->NewFloatArray(arr.size());
env->SetFloatArrayRegion(a, 0, arr.size(), arr.ptr());
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_DOUBLE: {
Array arr = *p_args[i];
jdoubleArray a = env->NewDoubleArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jdouble val = arr[j];
env->SetDoubleArrayRegion(a, j, 1, &val);
jdoubleArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewDoubleArray(arr.size());
for (int j = 0; j < arr.size(); j++) {
jdouble val = arr[j];
env->SetDoubleArrayRegion(a, j, 1, &val);
}
} else if (p_args[i]->get_type() == Variant::PACKED_FLOAT64_ARRAY) {
PackedFloat64Array arr = *p_args[i];
a = env->NewDoubleArray(arr.size());
env->SetDoubleArrayRegion(a, 0, arr.size(), arr.ptr());
}
argv[i].l = a;
to_free.push_back(a);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_STRING:
case ARG_ARRAY_BIT | ARG_TYPE_CHARSEQUENCE: {
Array arr = *p_args[i];
jobjectArray a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr);
for (int j = 0; j < arr.size(); j++) {
String s = arr[j];
jstring jStr = env->NewStringUTF(s.utf8().get_data());
env->SetObjectArrayElement(a, j, jStr);
to_free.push_back(jStr);
jobjectArray a = nullptr;
if (p_args[i]->get_type() == Variant::ARRAY) {
Array arr = *p_args[i];
a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr);
for (int j = 0; j < arr.size(); j++) {
String s = arr[j];
jstring jStr = env->NewStringUTF(s.utf8().get_data());
env->SetObjectArrayElement(a, j, jStr);
to_free.push_back(jStr);
}
} else if (p_args[i]->get_type() == Variant::PACKED_STRING_ARRAY) {
PackedStringArray arr = *p_args[i];
a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr);
for (int j = 0; j < arr.size(); j++) {
String s = arr[j];
jstring jStr = env->NewStringUTF(s.utf8().get_data());
env->SetObjectArrayElement(a, j, jStr);
to_free.push_back(jStr);
}
}
argv[i].l = a;
@ -410,7 +601,22 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
to_free.push_back(jarr);
} break;
case ARG_ARRAY_BIT | ARG_TYPE_CLASS: {
argv[i].l = nullptr;
String cn = method->param_sigs[i].operator String();
if (cn.begins_with("[L") && cn.ends_with(";")) {
cn = cn.substr(2, cn.length() - 3);
}
jclass c = env->FindClass(cn.utf8().get_data());
if (c) {
Array arr = *p_args[i];
jobjectArray jarr = env->NewObjectArray(arr.size(), c, nullptr);
for (int j = 0; j < arr.size(); j++) {
Ref<JavaObject> jo = arr[j];
env->SetObjectArrayElement(jarr, j, jo->instance);
}
argv[i].l = jarr;
to_free.push_back(jarr);
}
} break;
}
}