Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaKit: inout primitive arrays #156

Open
lhoward opened this issue Nov 7, 2024 · 5 comments
Open

JavaKit: inout primitive arrays #156

lhoward opened this issue Nov 7, 2024 · 5 comments
Labels

Comments

@lhoward
Copy link
Contributor

lhoward commented Nov 7, 2024

Presume this is on the TODO list :)

I'd like to use

@JavaClass("java.nio.ByteBuffer")
open class JavaNIOByteBuffer: JavaNIOBuffer {
...
  @JavaMethod
  open func get(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) -> JavaNIOByteBuffer!
...
}

but the projection of byte[] is not inout.

@lhoward
Copy link
Contributor Author

lhoward commented Nov 7, 2024

Feel free to close if known issue.

@lhoward
Copy link
Contributor Author

lhoward commented Nov 7, 2024

I'd also be happy with a special case for byte buffers that lives within JavaKit (there is precedence, JNI has one).

@ktoso ktoso changed the title inout primitive arrays JavaKit: inout primitive arrays Nov 7, 2024
@ktoso
Copy link
Collaborator

ktoso commented Nov 7, 2024

Issues are good, please keep em coming but I'd like to ask if you could qualify that they're all about "JavaKit" or "Java2Swift" because the same kinds of things need to be done in jextract -- it'll be easier to know which side of conversions the issue is about this way.

Anyway, lemme add tags :)

@ktoso ktoso added the javakit label Nov 7, 2024
@lhoward
Copy link
Contributor Author

lhoward commented Nov 7, 2024

Note to self: may be possible to use jniGetArrayRegion(). Essentially I'm just trying to bridge java.nio.ByteBuffer to/from Data.

@lhoward
Copy link
Contributor Author

lhoward commented Nov 7, 2024

Ah, it's tricky to implement this in Swift without reimplementing a lot of JavaKit. The options are really:

  • general support for inout parameters in JavaKit
  • specific ByteBuffer bridge in JavaKit that uses internal API
  • application-side Java wrapper function that returns a byte[]

To unblock progress (well, I was unblocked, but reading a byte at a time!), I've opted for the third option for now.

import FoundationEssentials
import JavaKit
import JavaRuntime

extension Data {
  func asJavaNIOByteBuffer() -> JavaNIOByteBuffer {
    let byteBufferClass = try! JavaClass<JavaNIOByteBuffer>()
    let byteBuffer = byteBufferClass.allocateDirect(Int32(count))!

    return byteBuffer.put(map { Int8(bitPattern: $0) }, 0, Int32(count))
  }
}

extension JavaNIOByteBuffer {
  func asData() throws -> Data {
    let array: [Int8]

    if hasArray() {
      let position = Int(position()), limit = Int(limit())
      let offset = Int(arrayOffset()) + position

      array = Array(self.array()[offset..<(offset + limit)])
    } else {
      array = try! JavaClass<ByteBufferHelper>(environment: javaEnvironment)
        .getByteBufferContents(self)
    }

    return Data(array.map { UInt8(bitPattern: $0) })
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants