Skip to content

jextract: support typed unsafepointer/unsafebufferpointer in FFM and JNI generators - #904

Open
Tatenda-k wants to merge 1 commit into
swiftlang:mainfrom
Tatenda-k:jextract-pointer-support
Open

jextract: support typed unsafepointer/unsafebufferpointer in FFM and JNI generators#904
Tatenda-k wants to merge 1 commit into
swiftlang:mainfrom
Tatenda-k:jextract-pointer-support

Conversation

@Tatenda-k

@Tatenda-k Tatenda-k commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Added support for case .unsafePointer, .unsafeMutablePointer, case .unsafePointer, .unsafeMutablePointer, and case .unsafeBufferPointer, .unsafeMutableBufferPointer for FFM and JNI.
#840

@Tatenda-k
Tatenda-k requested a review from ktoso as a code owner August 22, 2026 23:28
*/
public static java.lang.foreign.MemorySegment globalReturnUnsafeBufferPointer() {
try(var arena$ = Arena.ofConfined()) {
MemorySegment result$_pointer = arena$.allocate(SwiftValueLayout.SWIFT_POINTER);

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.

please format this a bit better

parameter: JavaParameter(name: parameterName, type: .javaForeignMemorySegment),
conversion: .commaSeparated([
.placeholder,
.constant("\(parameterName).byteSize() / \(elementLayout.description).byteSize()"),

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.

Suggested change
.constant("\(parameterName).byteSize() / \(elementLayout.description).byteSize()"),
// Calculate the element count: buffer size / element size
.constant("\(parameterName).byteSize() / \(elementLayout.description).byteSize()"),

* Corresponds to Swift's {@code UnsafeBufferPointer<T>} and
* {@code UnsafeMutableBufferPointer<T>}.
*/
public final class SwiftBufferPointer {

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.

This must be unsafe, we're not keeping the memory alive so it could be misleading to drop the Unsafe -- please let's name it

Suggested change
public final class SwiftBufferPointer {
public final class SwiftUnsafeBufferPointer {

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 think we should mirror the Mutable as well -- make a new type that is SwiftUnsafeMutableBufferPointer and we should import as it when possible


@Override
public String toString() {
return "SwiftBufferPointer(baseAddress=0x" + Long.toHexString(baseAddress) + ", count=" + count + ")";

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.

nice toString, thx

@ktoso ktoso left a comment

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.

Pretty good work! Almost there 👍

Please add runtime tests by adding functions returning such buffers to Samples/SwiftJavaExtractJNISampleApp/Sources/MySwiftLibrary and then adding tests in Java using them in Samples/SwiftJavaExtractJNISampleApp/src/test/java

@ktoso

ktoso commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Also same tests in FFM since we claim to support it now

outParameters: [.init(name: resultName, type: .swiftBufferPointer, allocation: .new)],
conversion: .constant(resultName),
)
//taenda todo: add support for UnsafeRawBufferPointer and UnsafeMutableRawBufferPointer

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.

let's address this TODO please

@Test
func returnUnsafeRawBufferPointer_javaBindings() throws {
try assertOutput(
dump: true,

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.

please don't commit with dump: true, it'll be very noisy in CI

SwiftBufferPointer o = (SwiftBufferPointer) other;
return this.baseAddress == o.baseAddress && this.count == o.count;
}

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.

So this is imported but isn't usable in Java, we should probably offer an toByteBuffer() here wdyt?

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