Godot ライブラリのヘッダーファイルを公開して iOS アプリケーションのコードから定義を参照する
Godot iOS アプリケーションの main 関数のありかを探るの最後に書いたように、Godot のライブラリは外部から参照される必要がないため、Godot の内部で定義されているクラスの情報などを公開していません。より具体的に言うと、Godot からエクスポートされる xcframework はヘッダーファイルを公開していませんし、アプリケーションのコードからインポートすらできません。
今回は、Godot からエクスポートされた xcframework をアプリケーションのコードからインポートできるようにして、Godot 側で定義されているクラスの情報をアプリケーション側で見えるようにします。
1. Godot からエクスポートされた xcframework の構成を確認する
Godot から godot_ios
という名前でプロジェクトをエクスポートした場合の xcframework の構成を確認します。
プロジェクト名 godot_ios
でエクスポートされた Godot の実装を含む xcframework
xcframework のディレクトリの中には、Info.plist
、実機向けのライブラリ、シミュレータ向けのライブラリが格納されています。
Info.plist
の中身を確認します。
Info.plist
のプレビュー
AvailableLibraries
の中に実機向け、シミュレータ向けのライブラリの情報が書かれています。眺めてみると、Item 0
が実機向け、Item 1
がシミュレータ向けであることが分かります。
この構成に手を加えて、Godot のライブラリをインポートして内部の定義が見える状態にします。
2. 公開するヘッダー情報を配置する
xcframework は内部に含まれるものの種類によって構成が変わってきますので、以下の手順は静的ライブラリ(*.a)から構成される xcframework に対してのみ成り立ちます。
Info.plist
にヘッダー情報の場所を記述する
2-1. Info.plist
にヘッダー情報が格納されている場所についての情報を追記します。以下のように HeadersPath
という項目を追加をして、値を Headers
とします。「Headers
にヘッダー情報があるよ」ということを伝えています。
Info.plist
のプレビュー(HeadersPath
追記後)
HeadersPath
に指定した名前のディレクトリを作成する
2-2. 指定した名前 Headers
のディレクトリを作成します。ディレクトリはライブラリ(*.a
)と同じ階層に作成します。
ライブラリ(*.a
)のある階層に指定した名前のディレクトリを作成する
2-3. Godot ライブラリのヘッダーファイルをコピーする
作成したディレクトリに、Godot の公開する情報に関するヘッダーファイルを配置します。godotengine/godot の platform/ios
にあるヘッダーファイルを、作成したディレクトリにコピーします。
platform/ios
にあるヘッダーファイルをコピーする
module.modulemap
と umbrella header を作成する
2-4. 指定したディレクトリにヘッダーファイルを配置しただけでは、情報は公開されません。module.modulemap
の記述によってインポートができるようになり、公開するヘッダー情報を記述することによって、インポートした側で情報が見えるようになります。今回は複数のヘッダーファイルを公開したいので、umbrella header に情報をまとめました。
module.modulemap
は以下のように記述しました。この後に作成する unbrella header ファイルの名前を umbrella.h
と指定しています。
module Godot {
umbrella header "umbrella.h"
export *
module * { export * }
}
umbrella.h
は以下のように記述しました。ここではアプリケーション側での動作の確認の為に最低限必要なヘッダー情報を記述しています。
#import "app_delegate.h"
#import "display_layer.h"
#import "godot_app_delegate.h"
#import "godot_view.h"
#import "view_controller.h"
module.modulemap
と umbrella.h
の作成後
ここまででアプリケーション側に情報を公開する準備はできましたが、アプリケーション側にはまだコードがないので、読み込みを確認するためのコードを用意します。
3. Swift ファイルを作成し、インポートできることを確認する
Xcode 上で Swift ファイルを作成し、ライブラリをインポートできることを確認します。main.swift
を作成して、import に続いて予測変換で指定したモジュール名 Godot
が出てくれば成功です。
アプリケーション側で Godot ライブラリがインポートできるようになったようす
Swift ファイルの作成後、初回のビルド時にはコンパイル時の Swift のバージョンが指定されていないというエラーが発生します。プロジェクトの Build Settings から該当の項目に値を設定しましょう。
Swift のバージョンが指定されていないエラーが発生したら設定する項目
また、Swift ファイルの作成時に Bridging Header を作成するか聞かれますが、アプリケーション側に Objective-C を追加する訳ではないので、不要です。
GodotApplicalitionDelegate
クラスへの参照で発生するリンカエラーを確認する
4. 万事がうまくいっている訳ではありません。
GodotApplicalitionDelegate
は Godot ライブラリの中でアプリケーションのライフサイクルと密接な関係にあり、Godot ライブラリをアプリケーション側から制御する為には必ず参照する必要のあるクラスです。
上記までの作業で main.swift
から、Godot の内部で定義されているクラスが見えるようになっているはずです。試しに GodotApplicalitionDelegate
のインスタンスを生成するコードを書いてみます。
import Foundation
import Godot
_ = Godot.GodotApplicalitionDelegate()
すると、少なくとも2023年10月21日時点の master ブランチからビルドしたライブラリでは、ビルドエラーが発生します。
GodotApplicalitionDelegate
のインスタンス化のコードを追加すると発生するエラー
このエラーは godot/platform/ios/app_delegate.mm に定義されている extern int gargc;
に起因するエラーです。
Godot アプリケーションでは、main 関数の引数を一時的にグローバル変数 gargc, gargv に保存し、アプリケーションの起動直後のタイミングで、この引数の値を参照しています。
つまり、このエラーは Godot 側のコードを修正しないと解消されないのですが、アプリケーションの起動直後に必要な処理と密接に関係しているため、単に extern についての記述を修正してリンカエラーを解消するだけでは十分ではなく、main 関数に渡される引数の扱い自体を見直す必要があります。アプリケーション側から Godot ライブラリを操作する構図を作る為には、アプリケーションの起動時の処理をアプリケーション側のコードで制御する必要があるからです。
この扱いについては、次回以降で見ていきます。
Discussion