Skip to content

Commit ef6229e

Browse files
committed
handles autogrneration initial
1 parent aa1f956 commit ef6229e

6 files changed

Lines changed: 107 additions & 60 deletions

File tree

prebindgen-ext/src/jni/jni_kotlin_ext.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,47 @@ impl JniExt {
107107
Ok(file.write(output_dir)?)
108108
}
109109

110+
/// Emit one Kotlin file per entry in `handles` — each becomes a
111+
/// `public class <ClassName>(initialPtr: Long) : NativeHandle(initialPtr)`
112+
/// with the standard `close()` + `private external fun freePtrViaJNI(ptr: Long)`
113+
/// destructor pair. The emitted class is exactly what hand-written
114+
/// shell-only typed handles used to be; pulling them through the
115+
/// generator removes the per-type copy-paste.
116+
///
117+
/// `handles` is `&[(rust_doc_name, kotlin_fqn)]`:
118+
/// * `rust_doc_name` — short Rust name shown in the class doc comment
119+
/// (e.g. `"Subscriber"`). Pure documentation, doesn't have to match
120+
/// anything in the Registry.
121+
/// * `kotlin_fqn` — package-qualified Kotlin class name
122+
/// (e.g. `"io.zenoh.jni.JNISubscriber"`). The package and class
123+
/// name are split on the last `.`.
124+
///
125+
/// Only the "standard `freePtrViaJNI` destructor" shape is emitted.
126+
/// Typed handles with non-standard destructors
127+
/// (e.g. `JNILivelinessToken::undeclare`) or with helper methods
128+
/// (e.g. `JNISession::declarePublisher`) stay hand-written — pass
129+
/// only the shell-only types here.
130+
pub fn write_typed_handles(
131+
&self,
132+
handles: &[(&str, &str)],
133+
output_dir: &Path,
134+
) -> Result<Vec<PathBuf>, WriteKotlinError> {
135+
let mut written = Vec::new();
136+
for (rust_doc_name, fqn) in handles {
137+
let (package, class_name) = match fqn.rsplit_once('.') {
138+
Some((p, c)) => (p.to_string(), c.to_string()),
139+
None => (String::new(), (*fqn).to_string()),
140+
};
141+
let file = KotlinFile {
142+
contents: render_typed_handle_source(&package, &class_name, rust_doc_name),
143+
package,
144+
class_name,
145+
};
146+
written.push(file.write(output_dir)?);
147+
}
148+
Ok(written)
149+
}
150+
110151
/// Return the `<rust-type-key> → <kotlin FQN>` map for every
111152
/// `impl Fn(args)` type the Registry has resolved. Use this to merge
112153
/// into a `KotlinTypeMap` consumed by the aggregated-interface
@@ -377,6 +418,39 @@ public open class NativeHandle(initial: Long) {
377418
.to_string()
378419
}
379420

421+
/// Render one typed-handle Kotlin source file. Matches the shape of
422+
/// the hand-written shell-only `JNI*.kt` files this replaces:
423+
///
424+
/// ```kotlin
425+
/// public class JNIFoo(initialPtr: Long) : NativeHandle(initialPtr) {
426+
/// fun close() = close { freePtrViaJNI(it) }
427+
/// private external fun freePtrViaJNI(ptr: Long)
428+
/// }
429+
/// ```
430+
///
431+
/// The Kotlin/JVM JNI name mangler binds `freePtrViaJNI` to the
432+
/// `Java_<pkg>_<class>_freePtrViaJNI` extern emitted on the Rust
433+
/// side — same convention as before, no Rust-side change needed.
434+
fn render_typed_handle_source(package: &str, class_name: &str, rust_doc_name: &str) -> String {
435+
let mut s = String::new();
436+
s.push_str("// Auto-generated by JniExt — do not edit by hand.\n");
437+
if !package.is_empty() {
438+
s.push_str(&format!("package {}\n\n", package));
439+
}
440+
s.push_str(&format!(
441+
"/** Typed [NativeHandle] for a native Zenoh `{}`. */\n",
442+
rust_doc_name
443+
));
444+
s.push_str(&format!(
445+
"public class {}(initialPtr: Long) : NativeHandle(initialPtr) {{\n",
446+
class_name
447+
));
448+
s.push_str(" public fun close() = close { freePtrViaJNI(it) }\n");
449+
s.push_str(" private external fun freePtrViaJNI(ptr: Long)\n");
450+
s.push_str("}\n");
451+
s
452+
}
453+
380454
/// Emit one safe top-level wrapper function per `#[prebindgen]` fn in
381455
/// `registry.functions`. Opaque-handle parameters (detected via the
382456
/// input converter returning `OwnedObject<T>`) become `NativeHandle`;
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
1-
//
2-
// Copyright (c) 2026 ZettaScale Technology
3-
//
4-
// This program and the accompanying materials are made available under the
5-
// terms of the Eclipse Public License 2.0 which is available at
6-
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7-
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8-
//
9-
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10-
//
11-
// Contributors:
12-
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13-
//
14-
1+
// Auto-generated by JniExt — do not edit by hand.
152
package io.zenoh.jni
163

174
/** Typed [NativeHandle] for a native Zenoh `MatchingListener`. */
185
public class JNIMatchingListener(initialPtr: Long) : NativeHandle(initialPtr) {
19-
fun close() = close { freePtrViaJNI(it) }
6+
public fun close() = close { freePtrViaJNI(it) }
207
private external fun freePtrViaJNI(ptr: Long)
218
}
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
1-
//
2-
// Copyright (c) 2026 ZettaScale Technology
3-
//
4-
// This program and the accompanying materials are made available under the
5-
// terms of the Eclipse Public License 2.0 which is available at
6-
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7-
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8-
//
9-
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10-
//
11-
// Contributors:
12-
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13-
//
14-
1+
// Auto-generated by JniExt — do not edit by hand.
152
package io.zenoh.jni
163

174
/** Typed [NativeHandle] for a native Zenoh `Queryable`. */
185
public class JNIQueryable(initialPtr: Long) : NativeHandle(initialPtr) {
19-
fun close() = close { freePtrViaJNI(it) }
6+
public fun close() = close { freePtrViaJNI(it) }
207
private external fun freePtrViaJNI(ptr: Long)
218
}
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
1-
//
2-
// Copyright (c) 2026 ZettaScale Technology
3-
//
4-
// This program and the accompanying materials are made available under the
5-
// terms of the Eclipse Public License 2.0 which is available at
6-
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7-
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8-
//
9-
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10-
//
11-
// Contributors:
12-
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13-
//
14-
1+
// Auto-generated by JniExt — do not edit by hand.
152
package io.zenoh.jni
163

174
/** Typed [NativeHandle] for a native Zenoh `SampleMissListener`. */
185
public class JNISampleMissListener(initialPtr: Long) : NativeHandle(initialPtr) {
19-
fun close() = close { freePtrViaJNI(it) }
6+
public fun close() = close { freePtrViaJNI(it) }
207
private external fun freePtrViaJNI(ptr: Long)
218
}
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
1-
//
2-
// Copyright (c) 2026 ZettaScale Technology
3-
//
4-
// This program and the accompanying materials are made available under the
5-
// terms of the Eclipse Public License 2.0 which is available at
6-
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7-
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8-
//
9-
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10-
//
11-
// Contributors:
12-
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13-
//
14-
1+
// Auto-generated by JniExt — do not edit by hand.
152
package io.zenoh.jni
163

174
/** Typed [NativeHandle] for a native Zenoh `Subscriber`. */
185
public class JNISubscriber(initialPtr: Long) : NativeHandle(initialPtr) {
19-
fun close() = close { freePtrViaJNI(it) }
6+
public fun close() = close { freePtrViaJNI(it) }
207
private external fun freePtrViaJNI(ptr: Long)
218
}

zenoh-jni/build.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,31 @@ fn main() {
472472
.expect("failed to write NativeHandle.kt");
473473
println!("cargo:warning=Wrote {}", nh_path.display());
474474

475+
// (4c.bis) Typed `NativeHandle` subclasses with the standard
476+
// `freePtrViaJNI` destructor shape. Only the shell-only
477+
// types are listed here — handles with non-standard
478+
// destructors (`JNILivelinessToken::undeclare`) or with
479+
// extra helper methods (`JNISession`, `JNIConfig`,
480+
// `JNIPublisher`, `JNIKeyExpr`, `JNIQuery`, `JNIQuerier`,
481+
// `JNIScout`, `JNIAdvancedSubscriber`,
482+
// `JNIAdvancedPublisher`) stay hand-written until their
483+
// helpers are split into sibling extension files.
484+
let typed_handles_written = ext
485+
.base
486+
.write_typed_handles(
487+
&[
488+
("Subscriber", "io.zenoh.jni.JNISubscriber"),
489+
("Queryable", "io.zenoh.jni.JNIQueryable"),
490+
("MatchingListener", "io.zenoh.jni.JNIMatchingListener"),
491+
("SampleMissListener", "io.zenoh.jni.JNISampleMissListener"),
492+
],
493+
kotlin_root,
494+
)
495+
.expect("failed to write typed-handle Kotlin classes");
496+
for path in &typed_handles_written {
497+
println!("cargo:warning=Wrote {}", path.display());
498+
}
499+
475500
// (4d) JNIWrappers.kt — one safe top-level wrapper per
476501
// `#[prebindgen]` fn. Opaque-handle params route through
477502
// `NativeHandle.withPtr` / `consume`; opaque returns wrap in

0 commit comments

Comments
 (0)