Skip to content

jextract/jni: Support non-JavaBoxable types in Dictionary#754

Open
sidepelican wants to merge 27 commits into
swiftlang:mainfrom
sidepelican:collection_boxable
Open

jextract/jni: Support non-JavaBoxable types in Dictionary#754
sidepelican wants to merge 27 commits into
swiftlang:mainfrom
sidepelican:collection_boxable

Conversation

@sidepelican
Copy link
Copy Markdown
Contributor

Problem

Currently, Dictionary only supports types that conform to JavaBoxable. This limitation prevents the use of dictionaries with custom or generated types, such as [Int: Fish].

Solution

I have introduced the JobjectBridge protocol, which allows us to define custom conversion logic for types when interacting with Java via jobject.

  • Existing JavaBoxable types are handled through a generic JavaBoxableBridge<T: JavaBoxable>.
  • For types generated by jextract, the generator now automatically creates a dedicated Bridge type form them.

Alternatives Considered

1. Type-specific native functions

Using dedicated native functions for each type to avoid jobject would be ideal, as it could leverage the existing translateResult mechanism and potentially reduce JNI overhead.
However, I couldn't find a viable way to implement this.

2. Direct protocol conformance

I considered having types conform directly to JobjectBridge.
However, this is problematic for classes with inheritance, as Swift does not allow a type to conform to the same protocol multiple times (which would be necessary at different levels of a class hierarchy). Introducing separate Bridge types effectively bypasses this limitation.

@sidepelican sidepelican requested a review from ktoso as a code owner May 15, 2026 02:55
@sidepelican
Copy link
Copy Markdown
Contributor Author

Note:: Tuples aren't supported in this PR yet.

1: Fish(name: "salmon"),
2: Fish(name: "clownfish"),
]
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic, thank you :)


import SwiftJava

public protocol JextractedTypeBridge: JobjectBridge {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea, but since it's pretty tricky, i'd like some docs how this is used here please


public static func fromJavaObject(_ obj: jobject?, in environment: JNIEnvironment) -> SwiftType {
guard let obj else {
fatalError("fromJavaObject received a null Java object")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe include the jclass as we crash here, so we at least know what type it was?

fromJNI value: jlong,
in environment: JNIEnvironment,
elementBridge: ElementBridge.Type
) where ElementBridge.SwiftType == Element {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, this is neat

@ktoso
Copy link
Copy Markdown
Collaborator

ktoso commented May 15, 2026

I'll review this some more later, gotta head offline soon but I like the overall approach, this looks pretty good already 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants