Skip to content

Prototyping Swift Array Accessor #207

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

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@ public class MySwiftClass {
p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
}

public var counter: Int32 = 0
public var counter: Int = 0

public func increment(by num: Int) -> Int {
counter += num
return counter
}

public func voidMethod() {
p("")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import SwiftKitSwift

@_cdecl("swiftjava_manual_getArrayMySwiftClass")
public func swiftjava_manual_getArrayMySwiftClass() -> UnsafeMutableRawPointer /* [MySwiftClass] */ {
p("[thunk] swiftjava_manual_getArrayMySwiftClass")
var array: [MySwiftClass] = getArrayMySwiftClass()
p("[thunk] swiftjava_manual_getArrayMySwiftClass -> \(array)")
// TODO: we need to retain it I guess as we escape it into Java
var ptr: UnsafeRawBufferPointer!
array.withUnsafeBytes {
ptr = $0
}
p("[thunk] swiftjava_manual_getArrayMySwiftClass -> \(ptr)")

return UnsafeMutableRawPointer(mutating: ptr!.baseAddress)!
}

@_cdecl("swiftjava_SwiftKitSwift_Array_count") // FIXME: hardcoded for MySwiftClass
public func swiftjava_SwiftKitSwift_Array_count(
rawPointer: UnsafeMutableRawPointer, // Array<T>
elementType: UnsafeMutableRawPointer // Metadata of T
) -> Int {
print("[swift][\(#fileID):\(#line)](\(#function) passed in rawPointer = \(rawPointer)")
print("[swift][\(#fileID):\(#line)](\(#function) passed in metadata = \(elementType)")

let array = rawPointer.assumingMemoryBound(to: [MySwiftClass].self)
.pointee

print("[swift][\(#fileID):\(#line)](\(#function) ARRAY count = \(array.count)")
print("[swift][\(#fileID):\(#line)](\(#function) ARRAY[0] = \(unsafeBitCast(array[0], to: UInt64.self))")
return array.count
}

@_cdecl("swiftjava_SwiftKitSwift_Array_get") // FIXME: hardcoded for MySwiftClass
public func swiftjava_SwiftKitSwift_Array_get(
rawPointer: UnsafeMutableRawPointer, // Array<T>
index: Int,
elementType: UnsafeMutableRawPointer // Metadata of T
) -> UnsafeMutableRawPointer {
print("[swift][\(#fileID):\(#line)](\(#function) passed in rawPointer = \(rawPointer)")
print("[swift][\(#fileID):\(#line)](\(#function) passed in index = \(index)")
print("[swift][\(#fileID):\(#line)](\(#function) passed in metadata = \(elementType)")

let array: UnsafeMutableBufferPointer<MySwiftClass> = UnsafeMutableBufferPointer(
start: rawPointer.assumingMemoryBound(to: MySwiftClass.self),
count: 999 // FIXME: we need this to be passed in
)

print("[swift][\(#fileID):\(#line)](\(#function) ARRAY[\(index)] = \(unsafeBitCast(array[index], to: UInt64.self))")
let object = array[index]

let objectPointer = unsafeBitCast(object, to: UnsafeMutableRawPointer.self)
return _swiftjava_swift_retain(object: objectPointer)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public func globalMakeInt() -> Int {
return 42
}

public func getMySwiftClassUntyped<T>(as: T.Type) -> Any {
return MySwiftClass(len: 1, cap: 2)
}

public func globalWriteString(string: String) -> Int {
return string.count
}
Expand All @@ -47,6 +51,30 @@ public func globalCallMeRunnable(run: () -> ()) {
run()
}

public func getArrayInt() -> [Int] {
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

let DATA = [
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

TODO: make it not global and deal with lifetime

MySwiftClass(len: 1, cap: 11),
MySwiftClass(len: 2, cap: 22),
MySwiftClass(len: 3, cap: 33),
]

public func getArrayMySwiftClass() -> [MySwiftClass] {
DATA
}


let BYTES_DATA: [UInt8] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
]


public func getByteArray() -> [UInt8] {
BYTES_DATA
}

public class MySwiftClass {

public var len: Int
Expand All @@ -64,7 +92,7 @@ public class MySwiftClass {

deinit {
let addr = unsafeBitCast(self, to: UInt64.self)
p("Deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
p("MySwiftClass.deinit, self = 0x\(String(addr, radix: 16, uppercase: true))")
}

public var counter: Int32 = 0
Expand All @@ -77,6 +105,15 @@ public class MySwiftClass {
p("i:\(i)")
}

// TODO: workaround until we expose properties again
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

TODO: Seems we didn't yet finish moving to the "thunk way" the properties, gotta do that.

public func getterForLen() -> Int {
len
}
// TODO: workaround until we expose properties again
public func getterForCap() -> Int {
cap
}

public func echoIntMethod(i: Int) -> Int {
p("i:\(i)")
return i
Expand All @@ -99,9 +136,9 @@ public class MySwiftClass {

// ==== Internal helpers

private func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
// print("[swift][\(file):\(line)](\(function)) \(msg)")
// fflush(stdout)
package func p(_ msg: String, file: String = #fileID, line: UInt = #line, function: String = #function) {
print("[swift][\(file):\(line)](\(function)) \(msg)")
fflush(stdout)
}

#if os(Linux)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

#if os(Linux)
import Glibc
#else
import Darwin.C
#endif

public struct MySwiftStruct {
private var numberA: Int
private var numberB: Int
private var numberC: Int
private var numberD: Int

public init(number: Int) {
self.numberA = number
self.numberB = number
self.numberC = number
self.numberD = number
}

public func getTheNumber() -> Int {
numberA
}
}

public struct MyHugeSwiftStruct {
private var numberA: Int
private var numberB: Int
private var numberC: Int
private var numberD: Int

private var numberA2: Int = 0
private var numberB2: Int = 0
private var numberC2: Int = 0
private var numberD2: Int = 0

public init(number: Int) {
self.numberA = number
self.numberB = number
self.numberC = number
self.numberD = number
}

public func getTheNumber() -> Int {
numberA
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

// Import swift-extract generated sources

import com.example.swift.MySwiftLibrary;
import com.example.swift.MySwiftClass;

// Import javakit/swiftkit support libraries
import org.swift.swiftkit.SwiftAnyType;
import org.swift.swiftkit.SwiftArena;
import org.swift.swiftkit.SwiftArrayRef;
import org.swift.swiftkit.SwiftKit;
import org.swift.swiftkit.SwiftValueWitnessTable;

import java.util.Arrays;
import java.lang.foreign.GroupLayout;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.SequenceLayout;

public class HelloJava2Swift {

Expand All @@ -38,26 +38,74 @@ public static void main(String[] args) {
}

static void examples() {
MySwiftLibrary.helloWorld();
// MySwiftLibrary.helloWorld();
//
// MySwiftLibrary.globalTakeInt(1337);
//
// // Example of using an arena; MyClass.deinit is run at end of scope
// try (var arena = SwiftArena.ofConfined()) {
// MySwiftClass obj = new MySwiftClass(arena, 2222, 7777);
//
// // just checking retains/releases work
// SwiftKit.retain(obj.$memorySegment());
// SwiftKit.release(obj.$memorySegment());
//
// obj.voidMethod();
// obj.takeIntMethod(42);
// }

// public func getArrayMySwiftClass() -> [MySwiftClass]
SwiftArrayRef<MySwiftClass> arr = ManualImportedMethods.getArrayMySwiftClass();

// precondition(3, arr.count());

MySwiftClass first = arr.get(0);
System.out.println("[java] first = " + first);

// FIXME: properties don't work yet, need the thunks!
// System.out.println("[java] first.getLen() = " + first.getLen());
// assert(first.getLen() == 1);
// System.out.println("[java] first.getCap() = " + first.getCap());
// assert(first.getCap() == 2);

MySwiftLibrary.globalTakeInt(1337);
System.out.println("[java] first.getterForLen() = " + first.getterForLen());
System.out.println("[java] first.getForCap() = " + first.getterForCap());
precondition(1, first.getterForLen());
precondition(11, first.getterForCap());

MySwiftClass second = arr.get(1);
precondition(2, second.getterForLen());
precondition(22, second.getterForCap());

// Example of using an arena; MyClass.deinit is run at end of scope
try (var arena = SwiftArena.ofConfined()) {
MySwiftClass obj = new MySwiftClass(arena, 2222, 7777);
var struct = new MySwiftStruct(arena, 44);
// System.out.println("struct.getTheNumber() = " + struct.getTheNumber());
// long theNumber = struct.getTheNumber();
// precondition(44, theNumber);

// just checking retains/releases work
SwiftKit.retain(obj.$memorySegment());
SwiftKit.release(obj.$memorySegment());
System.out.println("struct.$layout() = " + struct.$layout());
System.out.println("struct.$layout() = " + struct.$layout().byteSize());

obj.voidMethod();
obj.takeIntMethod(42);
var huge = new MyHugeSwiftStruct(arena, 44);
System.out.println("huge.$layout() = " + huge.$layout());
System.out.println("huge.$layout() = " + huge.$layout().byteSize());
}


arr.get(0);


System.out.println("DONE.");
}

private static void precondition(long expected, long got) {
if (expected != got) {
throw new AssertionError("Expected '" + expected + "', but got '" + got + "'!");
}
}

public static native long jniWriteString(String str);
public static native long jniGetInt();

}

Loading