From 21991c5ce8d4428a6ede93a643153abefd540b84 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Wed, 10 Jul 2024 13:06:07 +0200 Subject: [PATCH] Kotlin: Switch to JNA direct mapping According to https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md direct mapping can improve performance substantially, maybe even that of custom JNI. Given we know all methods it's easy to switch it all over. Note that I have not run any actual benchmark to see how it helps. --- .../src/bindings/kotlin/gen_kotlin/mod.rs | 8 ++--- .../templates/NamespaceLibraryTemplate.kt | 35 +++++++++---------- .../kotlin/templates/ObjectTemplate.kt | 4 +-- .../kotlin/templates/RustBufferTemplate.kt | 4 +-- .../src/bindings/kotlin/templates/macros.kt | 6 ++-- 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs b/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs index 92f2f39c33..f483cb17f2 100644 --- a/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs +++ b/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs @@ -669,7 +669,7 @@ mod filters { ) -> Result { let ffi_func = callable.ffi_rust_future_poll(ci); Ok(format!( - "{{ future, callback, continuation -> UniffiLib.INSTANCE.{ffi_func}(future, callback, continuation) }}" + "{{ future, callback, continuation -> UniffiLib.{ffi_func}(future, callback, continuation) }}" )) } @@ -678,7 +678,7 @@ mod filters { ci: &ComponentInterface, ) -> Result { let ffi_func = callable.ffi_rust_future_complete(ci); - let call = format!("UniffiLib.INSTANCE.{ffi_func}(future, continuation)"); + let call = format!("UniffiLib.{ffi_func}(future, continuation)"); let call = match callable.return_type() { Some(Type::External { kind: ExternalKind::DataClass, @@ -699,9 +699,7 @@ mod filters { ci: &ComponentInterface, ) -> Result { let ffi_func = callable.ffi_rust_future_free(ci); - Ok(format!( - "{{ future -> UniffiLib.INSTANCE.{ffi_func}(future) }}" - )) + Ok(format!("{{ future -> UniffiLib.{ffi_func}(future) }}")) } /// Remove the "`" chars we put around function/variable names diff --git a/uniffi_bindgen/src/bindings/kotlin/templates/NamespaceLibraryTemplate.kt b/uniffi_bindgen/src/bindings/kotlin/templates/NamespaceLibraryTemplate.kt index 1bac8a435c..bd438be9e5 100644 --- a/uniffi_bindgen/src/bindings/kotlin/templates/NamespaceLibraryTemplate.kt +++ b/uniffi_bindgen/src/bindings/kotlin/templates/NamespaceLibraryTemplate.kt @@ -59,28 +59,25 @@ internal open class {{ ffi_struct.name()|ffi_struct_name }}( // A JNA Library to expose the extern-C FFI definitions. // This is an implementation detail which will be called internally by the public API. -internal interface UniffiLib : Library { - companion object { - internal val INSTANCE: UniffiLib by lazy { - loadIndirect(componentName = "{{ ci.namespace() }}") - .also { lib: UniffiLib -> - uniffiCheckContractApiVersion(lib) - uniffiCheckApiChecksums(lib) - {% for fn in self.initialization_fns() -%} - {{ fn }}(lib) - {% endfor -%} - } - } - {% if ci.contains_object_types() %} - // The Cleaner for the whole library - internal val CLEANER: UniffiCleaner by lazy { - UniffiCleaner.create() - } - {%- endif %} +internal object UniffiLib { + {% if ci.contains_object_types() %} + // The Cleaner for the whole library + internal val CLEANER: UniffiCleaner by lazy { + UniffiCleaner.create() + } + {% endif %} + + init { + Native.register(findLibraryName(componentName = "{{ ci.namespace() }}")) + uniffiCheckContractApiVersion(this) + uniffiCheckApiChecksums(this) + {% for fn in self.initialization_fns() -%} + {{ fn }}(this) + {% endfor %} } {% for func in ci.iter_ffi_function_definitions() -%} - fun {{ func.name() }}( + @JvmStatic external fun {{ func.name() }}( {%- call kt::arg_list_ffi_decl(func) %} ): {% match func.return_type() %}{% when Some with (return_type) %}{{ return_type.borrow()|ffi_type_name_by_value }}{% when None %}Unit{% endmatch %} {% endfor %} diff --git a/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt b/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt index 72fdbe5648..ea5ab244fd 100644 --- a/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt +++ b/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt @@ -195,7 +195,7 @@ open class {{ impl_class_name }}: Disposable, AutoCloseable, {{ interface_name } override fun run() { pointer?.let { ptr -> uniffiRustCall { status -> - UniffiLib.INSTANCE.{{ obj.ffi_object_free().name() }}(ptr, status) + UniffiLib.{{ obj.ffi_object_free().name() }}(ptr, status) } } } @@ -203,7 +203,7 @@ open class {{ impl_class_name }}: Disposable, AutoCloseable, {{ interface_name } fun uniffiClonePointer(): Pointer { return uniffiRustCall() { status -> - UniffiLib.INSTANCE.{{ obj.ffi_object_clone().name() }}(pointer!!, status) + UniffiLib.{{ obj.ffi_object_clone().name() }}(pointer!!, status) } } diff --git a/uniffi_bindgen/src/bindings/kotlin/templates/RustBufferTemplate.kt b/uniffi_bindgen/src/bindings/kotlin/templates/RustBufferTemplate.kt index b28f25bfc3..a897f533b5 100644 --- a/uniffi_bindgen/src/bindings/kotlin/templates/RustBufferTemplate.kt +++ b/uniffi_bindgen/src/bindings/kotlin/templates/RustBufferTemplate.kt @@ -22,7 +22,7 @@ open class RustBuffer : Structure() { companion object { internal fun alloc(size: ULong = 0UL) = uniffiRustCall() { status -> // Note: need to convert the size to a `Long` value to make this work with JVM. - UniffiLib.INSTANCE.{{ ci.ffi_rustbuffer_alloc().name() }}(size.toLong(), status) + UniffiLib.{{ ci.ffi_rustbuffer_alloc().name() }}(size.toLong(), status) }.also { if(it.data == null) { throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})") @@ -38,7 +38,7 @@ open class RustBuffer : Structure() { } internal fun free(buf: RustBuffer.ByValue) = uniffiRustCall() { status -> - UniffiLib.INSTANCE.{{ ci.ffi_rustbuffer_free().name() }}(buf, status) + UniffiLib.{{ ci.ffi_rustbuffer_free().name() }}(buf, status) } } diff --git a/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt b/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt index b2f909ef3a..beda1fd832 100644 --- a/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt +++ b/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt @@ -21,7 +21,7 @@ {%- else %} uniffiRustCall() {%- endmatch %} { _status -> - UniffiLib.INSTANCE.{{ func.ffi_func().name() }}( + UniffiLib.{{ func.ffi_func().name() }}( {% if func.takes_self() %}it, {% endif -%} {% call arg_list_lowered(func) -%} _status) @@ -60,13 +60,13 @@ uniffiRustCallAsync( {%- if callable.takes_self() %} callWithPointer { thisPtr -> - UniffiLib.INSTANCE.{{ callable.ffi_func().name() }}( + UniffiLib.{{ callable.ffi_func().name() }}( thisPtr, {% call arg_list_lowered(callable) %} ) }, {%- else %} - UniffiLib.INSTANCE.{{ callable.ffi_func().name() }}({% call arg_list_lowered(callable) %}), + UniffiLib.{{ callable.ffi_func().name() }}({% call arg_list_lowered(callable) %}), {%- endif %} {{ callable|async_poll(ci) }}, {{ callable|async_complete(ci) }},