Skip to content

Commit 25e72ab

Browse files
committed
explicit arc decode ref
1 parent 81ebc74 commit 25e72ab

4 files changed

Lines changed: 36 additions & 38 deletions

File tree

zenoh-flat/src/jni_converter.rs

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7669
impl 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

zenoh-jni/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zenoh-jni/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ prebindgen = "0.4.1"
5252
zenoh-flat = { path = "../zenoh-flat", features = ["zenoh-ext"] }
5353
itertools = "0.12"
5454
syn = "2"
55+
quote = "1"
5556

5657
[profile.release]
5758
debug = false # If you want debug symbol in release mode, set the env variable: RUSTFLAGS=-g

zenoh-jni/build.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use itertools::Itertools;
2+
use quote::quote;
23
use zenoh_flat::jni_converter::{
3-
ArgDecode, JniForm, JniMethodsConverter, JniStructConverter, ReturnEncode, ReturnForm,
4-
TypeBinding,
4+
ArgDecode, InlineFn, JniForm, JniMethodsConverter, JniStructConverter, ReturnEncode,
5+
ReturnForm, TypeBinding,
56
};
67
use zenoh_flat::jni_type_binding::JniTypeBinding;
78

@@ -87,7 +88,9 @@ fn shared_bindings() -> JniTypeBinding {
8788
JniForm::new(
8889
"*const zenoh::key_expr::KeyExpr<'static>",
8990
"Long",
90-
ArgDecode::ConsumeArc,
91+
ArgDecode::Inline(InlineFn::new(|input| {
92+
quote! { (*std::sync::Arc::from_raw(#input)).clone() }
93+
})),
9194
)
9295
.pointer_param(true),
9396
),

0 commit comments

Comments
 (0)