fortran66のブログ

fortran について書きます。

【メモ帳】Fortran で Mac SwiftUI 利用

AI 様に Fortran から Mac SwiftUI 利用してもらう

MacGUI がどうなっているのか全く知らないのですが、古い Objective C 時代のものと、新しい SwiftUI のものがあるらしいというのは噂に聞いています。

ChatGPT4o に fortran から SwiftUI 使えるか?と聞いたところ、C インターフェースかますことで出来るということで、簡単な例を作ってくれました。swift で DLL を作り Fortran からそれを呼びます。ほぼ無修正で動作しました。AI スンバラすい!

実行結果

% swiftc -emit-library -o libText.dylib text.swift -Xlinker -install_name -Xlinker @rpath/libText.dylib
% gfortran -o text text.f90 -L. -lText                                                                 
% ./text

ソース・プログラム

import Cocoa
import SwiftUI

@_cdecl("startSwiftUIWithMessage")
public func startSwiftUIWithMessage(message: UnsafePointer<CChar>) {
    let messageString = String(cString: message)
    if #available(macOS 10.15, *) {
        let app = NSApplication.shared
        let delegate = AppDelegate(message: messageString)
        app.delegate = delegate
        app.run()
    }
}

@available(macOS 10.15, *)
class AppDelegate: NSObject, NSApplicationDelegate {
    var window: NSWindow!
    var message: String

    init(message: String) {
        self.message = message
    }

    func applicationDidFinishLaunching(_ notification: Notification) {
        let contentView = ContentView(message: message)

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .resizable, .miniaturizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.isReleasedWhenClosed = false
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

    func applicationWillTerminate(_ notification: Notification) {
        // Cleanup code
    }
}

struct ContentView: View {
    var message: String

    var body: some View {
        Text(message)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
program call_swiftui
  use iso_c_binding
  implicit none

  interface
    subroutine startSwiftUIWithMessage(message) bind(C, name="startSwiftUIWithMessage")
      import :: c_char
      character(kind=c_char), intent(in) :: message(*)
    end subroutine startSwiftUIWithMessage
  end interface

  character(len=100) :: message

  ! Set the message to be passed to SwiftUI
  message = "Hello from Modern Fortran!"

  ! Call the SwiftUI function with the message
  call startSwiftUIWithMessage(trim(adjustl(message))//c_null_char)

end program call_swiftui