@@ -64,13 +64,6 @@ pub enum ArgDecode {
6464 /// ident. Used for trivial conversions like `bool` (`x != 0`) or
6565 /// `Duration` (`Duration::from_millis(x as u64)`).
6666 Inline ( InlineFn ) ,
67- /// `let <name> = <owned_object>::from_raw(<input>);` — borrows the Arc
68- /// pointed to by `<input>` via the converter-wide `owned_object` setting.
69- /// The argument is passed to the wrapped function as `&<name>`.
70- OwnedRef ,
71- /// Consume an `Arc<T>` raw pointer: reconstructs the Arc, clones the
72- /// inner value, and drops the Arc at end of scope.
73- ConsumeArc ,
7467}
7568
7669impl ArgDecode {
@@ -130,8 +123,14 @@ pub struct JniForm {
130123 /// `"String"`, `"ByteArray"`, `"JObject"`).
131124 kotlin_jni_type : String ,
132125 /// True for raw-pointer slots — appends `"Ptr"` to the Kotlin parameter
133- /// name (e.g. `sessionPtr: Long`).
126+ /// name (e.g. `sessionPtr: Long`) and drives `_ptr` rename in the JNI
127+ /// wrapper signature.
134128 pointer_param : bool ,
129+ /// When true, the decoded value is passed to the wrapped function as
130+ /// `&name` rather than `name`. Used for opaque-handle borrows where the
131+ /// decoder produces an owner (e.g. `OwnedObject`) but the wrapped
132+ /// function expects a shared reference.
133+ call_with_ref : bool ,
135134 decode : ArgDecode ,
136135}
137136
@@ -145,6 +144,7 @@ impl JniForm {
145144 jni_type : syn:: parse_str ( jni_type. as_ref ( ) ) . expect ( "invalid JniForm jni_type" ) ,
146145 kotlin_jni_type : kotlin_jni_type. into ( ) ,
147146 pointer_param : false ,
147+ call_with_ref : false ,
148148 decode,
149149 }
150150 }
@@ -154,6 +154,11 @@ impl JniForm {
154154 self
155155 }
156156
157+ pub fn call_with_ref ( mut self , v : bool ) -> Self {
158+ self . call_with_ref = v;
159+ self
160+ }
161+
157162 /// Whether this form's wire JNI type is a `JObject`-shaped object that
158163 /// supports `is_null()` (used by the `Option<T>` combinator).
159164 fn is_jni_object ( & self ) -> bool {
@@ -994,16 +999,24 @@ impl JniMethodsConverter {
994999 } ;
9951000 }
9961001 }
997- // Fallback: treat any unbound `&T` as an `OwnedRef` against a
998- // raw `*const T` pointer, decoded via the converter-wide
999- // `owned_object`. This matches the legacy `OpaqueRef` path.
1002+ // Fallback: treat any unbound `&T` as an opaque Arc borrow
1003+ // against a raw `*const T` pointer. The owned_object path is
1004+ // serialized to String (syn::Path is not Send) and re-parsed
1005+ // inside the closure. call_with_ref causes the decoded owner
1006+ // to be passed as `&name` to the wrapped function.
10001007 let ptr_ty: syn:: Type = syn:: parse2 ( quote ! { * const #elem } )
10011008 . expect ( "opaque pointer type must parse" ) ;
1009+ let owned_str = self . cfg . owned_object . to_token_stream ( ) . to_string ( ) ;
10021010 let opaque_form = JniForm {
10031011 jni_type : ptr_ty,
10041012 kotlin_jni_type : "Long" . to_string ( ) ,
10051013 pointer_param : true ,
1006- decode : ArgDecode :: OwnedRef ,
1014+ call_with_ref : true ,
1015+ decode : ArgDecode :: Inline ( InlineFn :: new ( move |input| {
1016+ let owned: syn:: Path =
1017+ syn:: parse_str ( & owned_str) . expect ( "owned_object must be a valid path" ) ;
1018+ quote ! { #owned:: from_raw( #input) }
1019+ } ) ) ,
10071020 } ;
10081021 ArgKind :: Borrow {
10091022 form : opaque_form,
@@ -1173,7 +1186,7 @@ impl JniMethodsConverter {
11731186 #[ allow( clippy:: too_many_arguments) ]
11741187 fn emit_consume_or_borrow (
11751188 & self ,
1176- borrow : bool ,
1189+ _borrow : bool ,
11771190 form : JniForm ,
11781191 kotlin_override : Option < String > ,
11791192 name : & syn:: Ident ,
@@ -1185,8 +1198,7 @@ impl JniMethodsConverter {
11851198 kt_enabled : bool ,
11861199 ) {
11871200 let jt = & form. jni_type ;
1188- let pat = if matches ! ( form. decode, ArgDecode :: OwnedRef | ArgDecode :: ConsumeArc ) {
1189- // Raw-pointer slots get a `_ptr` ident in the JNI signature.
1201+ let pat = if form. pointer_param {
11901202 format_ident ! ( "{}_ptr" , name)
11911203 } else {
11921204 name. clone ( )
@@ -1207,21 +1219,9 @@ impl JniMethodsConverter {
12071219 let expr = f. call ( & pat) ;
12081220 prelude. push ( quote ! { let #name = #expr; } ) ;
12091221 }
1210- ArgDecode :: OwnedRef => {
1211- let owned = & self . cfg . owned_object ;
1212- prelude. push ( quote ! { let #name = #owned:: from_raw( #pat) ; } ) ;
1213- }
1214- ArgDecode :: ConsumeArc => {
1215- let arc_ident = format_ident ! ( "__{}_arc" , name) ;
1216- prelude. push ( quote ! {
1217- let #arc_ident = std:: sync:: Arc :: from_raw( #pat) ;
1218- let #name = ( * #arc_ident) . clone( ) ;
1219- } ) ;
1220- }
12211222 }
12221223
1223- if borrow && matches ! ( form. decode, ArgDecode :: OwnedRef ) {
1224- // OwnedRef pattern: pass `&name` to match historical OpaqueRef behavior.
1224+ if form. call_with_ref {
12251225 call_args. push ( quote ! { & #name } ) ;
12261226 } else {
12271227 call_args. push ( quote ! { #name } ) ;
@@ -1244,13 +1244,6 @@ impl JniMethodsConverter {
12441244 ArgDecode :: EnvRef ( path) => quote ! { #path( & env, & #input) ? } ,
12451245 ArgDecode :: Pure ( path) => quote ! { #path( #input) ? } ,
12461246 ArgDecode :: Inline ( f) => f. call ( input) ,
1247- ArgDecode :: OwnedRef => {
1248- let owned = & self . cfg . owned_object ;
1249- quote ! { #owned:: from_raw( #input) }
1250- }
1251- ArgDecode :: ConsumeArc => {
1252- quote ! { ( * std:: sync:: Arc :: from_raw( #input) ) . clone( ) }
1253- }
12541247 }
12551248 }
12561249
0 commit comments