@@ -7,12 +7,6 @@ private fun findLibraryName(componentName: String): String {
77 return " {{ config.cdylib_name() }}"
88}
99
10- private inline fun <reified Lib : Library > loadIndirect (
11- componentName : String
12- ): Lib {
13- return Native .load<Lib >(findLibraryName(componentName), Lib ::class .java)
14- }
15-
1610// Define FFI callback types
1711{%- for def in ci.ffi_definitions() % }
1812{%- match def % }
@@ -55,88 +49,61 @@ internal open class {{ ffi_struct.name()|ffi_struct_name }}(
5549{%- endmatch % }
5650{%- endfor % }
5751
58-
5952{%- macro decl_kotlin_functions(func_list) -% }
6053{% for func in func_list -% }
61- fun {{ func.name () }}(
54+ external fun {{ func.name () }}(
6255 {%- call kt::arg_list_ffi_decl(func) % }
6356): {% match func.return_type() % }{% when Some with (return_type) % }{{ return_type.borrow()|ffi_type_name_by_value(ci) }}{% when None % }Unit {% endmatch % }
6457{% endfor % }
6558{%- endmacro % }
6659
60+ // A JNA Library to expose the extern-C FFI definitions.
61+ // This is an implementation detail which will be called internally by the public API.
62+
6763// For large crates we prevent `MethodTooLargeException` (see #2340)
68- // N.B. the name of the extension is very misleading, since it is
69- // rather `InterfaceTooLargeException`, caused by too many methods
64+ // N.B. the name of the extension is very misleading, since it is
65+ // rather `InterfaceTooLargeException`, caused by too many methods
7066// in the interface for large crates.
7167//
7268// By splitting the otherwise huge interface into two parts
73- // * UniffiLib
74- // * IntegrityCheckingUniffiLib (this)
69+ // * UniffiLib (this)
70+ // * IntegrityCheckingUniffiLib
71+ // And all checksum methods are put into `IntegrityCheckingUniffiLib`
7572// we allow for ~2x as many methods in the UniffiLib interface.
76- //
77- // The `ffi_uniffi_contract_version` method and all checksum methods are put
78- // into `IntegrityCheckingUniffiLib` and these methods are called only once,
79- // when the library is loaded.
80- internal interface IntegrityCheckingUniffiLib : Library {
81- // Integrity check functions only
82- {# newline below wanted #}
83-
84- {%- call decl_kotlin_functions(ci.iter_ffi_function_integrity_checks()) % }
85- }
86-
87- // A JNA Library to expose the extern-C FFI definitions.
88- // This is an implementation detail which will be called internally by the public API.
89- internal interface UniffiLib : Library {
90- companion object {
91- internal val INSTANCE : UniffiLib by lazy {
92- val componentName = " {{ ci.namespace() }}"
93- // For large crates we prevent `MethodTooLargeException` (see #2340)
94- // N.B. the name of the extension is very misleading, since it is
95- // rather `InterfaceTooLargeException`, caused by too many methods
96- // in the interface for large crates.
97- //
98- // By splitting the otherwise huge interface into two parts
99- // * UniffiLib (this)
100- // * IntegrityCheckingUniffiLib
101- // And all checksum methods are put into `IntegrityCheckingUniffiLib`
102- // we allow for ~2x as many methods in the UniffiLib interface.
103- //
104- // Thus we first load the library with `loadIndirect` as `IntegrityCheckingUniffiLib`
105- // so that we can (optionally!) call `uniffiCheckApiChecksums`...
106- loadIndirect<IntegrityCheckingUniffiLib >(componentName)
107- .also { lib: IntegrityCheckingUniffiLib ->
108- uniffiCheckContractApiVersion(lib)
73+ //
74+ // Note: above all written when we used JNA's `loadIndirect` etc.
75+ // We now use JNA's "direct mapping" - unclear if same considerations apply exactly.
76+ internal object IntegrityCheckingUniffiLib {
77+ init {
78+ Native .register(findLibraryName(componentName = " {{ ci.namespace() }}" ))
79+ uniffiCheckContractApiVersion(this )
10980{%- if ! config.omit_checksums % }
110- uniffiCheckApiChecksums(lib )
81+ uniffiCheckApiChecksums(this )
11182{%- endif % }
112- }
113- // ... and then we load the library as `UniffiLib`
114- // N.B. we cannot use `loadIndirect` once and then try to cast it to `UniffiLib`
115- // => results in `java.lang.ClassCastException: com.sun.proxy.$Proxy cannot be cast to ...`
116- // error. So we must call `loadIndirect` twice. For crates large enough
117- // to trigger this issue, the performance impact is negligible, running on
118- // a macOS M1 machine the `loadIndirect` call takes ~50ms.
119- val lib = loadIndirect<UniffiLib >(componentName)
120- // No need to check the contract version and checksums, since
121- // we already did that with `IntegrityCheckingUniffiLib` above.
122- {% for fn_item in self.initialization_fns(ci) -% }
123- {{ fn_item }}
124- {% endfor -% }
125- // Loading of library with integrity check done.
126- lib
127- }
128- {% if ci.contains_object_types() % }
129- // The Cleaner for the whole library
130- internal val CLEANER : UniffiCleaner by lazy {
131- UniffiCleaner .create()
132- }
133- {%- endif % }
13483 }
84+ {% filter indent(4 ) % }
85+ {%- call decl_kotlin_functions(ci.iter_ffi_function_integrity_checks()) % }
86+ {% endfilter % }
87+ }
13588
136- // FFI functions
137- {# newline below before call decl_kotlin_functions is needed #}
89+ internal object UniffiLib {
90+ {% if ci.contains_object_types() % }
91+ // The Cleaner for the whole library
92+ internal val CLEANER : UniffiCleaner by lazy {
93+ UniffiCleaner .create()
94+ }
95+ {% endif % }
13896
97+ init {
98+ Native .register(findLibraryName(componentName = " {{ ci.namespace() }}" ))
99+ {% for fn_item in self.initialization_fns(ci) -% }
100+ {{ fn_item }}
101+ {% endfor % }
102+ }
103+ {#- XXX - this `filter indent` doesn' t seem to work, even though the one above does? #}
104+ {% filter indent(4) %}
139105 {%- call decl_kotlin_functions(ci.iter_ffi_function_definitions_excluding_integrity_checks()) %}
106+ {% endfilter %}
140107}
141108
142109private fun uniffiCheckContractApiVersion(lib: IntegrityCheckingUniffiLib) {
@@ -164,5 +131,8 @@ private fun uniffiCheckApiChecksums(lib: IntegrityCheckingUniffiLib) {
164131 * @suppress
165132 */
166133public fun uniffiEnsureInitialized() {
167- UniffiLib .INSTANCE
134+ IntegrityCheckingUniffiLib
135+ // UniffiLib() initialized as objects are used, but we still need to explicitly
136+ // reference it so initialization across crates works as expected.
137+ UniffiLib
168138}
0 commit comments