C++ SDL アプリケーションの Android への移植

この投稿では、3D エディタのプロトタイプを移植した私の経験について説明します キューブ アート プロジェクト
まず、赤い 3D キューブ カーソルを持つエディタがエミュレータで実行されている結果を見てみましょう。

組み立てを成功させるには、次のことを行う必要がありました:

<オル>

  • 最新の Android SDK と NDK をインストールします(NDK バージョンは新しいほど良いです)
  • SDL2 ソース コードをダウンロードし、そこからテンプレートを取得して Android アプリケーションを構築します。
  • SDL イメージ、SDL ミキサーをアセンブリに追加します。
  • ゲーム エンジンとツールキットのライブラリ、それらの依存関係 (GLM、モダン C++ 用の JSON) を追加します
  • アセンブリ ファイルを Gradle に適合させる。
  • Android との互換性のために C++ コードを調整し、影響を受けるプラットフォーム依存コンポーネント(OpenGL ES、グラフィックス コンテキストの初期化)を変更する
  • エミュレータ上でプロジェクトをビルドしてテストします。
  • プロジェクト テンプレート

    ソース SDL、SDL イメージ、SDL ミキサーの読み込み:
    https://www.libsdl.org/download-2.0.php
    docs フォルダーには、Android プロジェクト テンプレートを使用するための詳細な手順が含まれています。 android-project ディレクトリを別のフォルダーにコピーするか、シンボリックリンクを作成するか、SDL フォルダーを android-project/app/jni にコピーします。
    avd フラグを正しい識別子に置き換えて、Sdk:

    ディレクトリから Android エミュレータを起動します。

    cd ~/Android/Sdk/emulator
    ./emulator -avd Pixel_2_API_24
    
    

    スクリプトでパスを指定し、プロジェクトをアセンブルします。

    rm -rf app/build || true
    export ANDROID_HOME=/home/demensdeum/Android/Sdk/
    export ANDROID_NDK_HOME=/home/demensdeum/Android/android-ndk-r21-beta2/
    ./gradlew clean build
    ./gradlew installDebug
    
    

    ファイルからの C コードを含む SDL プロジェクト テンプレートをアセンブルする必要があります

    android-sdl-test-app/cube-art-project-android/app/jni/src/YourSourceHere.c
    
    

    依存関係

    SDL_image、SDL_mixer のソース コードをアーカイブからダウンロードします。
    https://www.libsdl.org/projects/SDL_image/
    https://www.libsdl.org/projects/SDL_mixer/

    プロジェクトの依存関係(共有ライブラリなど)を読み込みます。
    https://gitlab.com/demensdeum/FlameSteelCore/
    https://gitlab.com/demensdeum/FlameSteelCommonTraits
    https://gitlab.com/demensdeum/FlameSteelBattleHorn
    https://gitlab.com/demensdeum/FlameSteelEngineGameToolkit/
    https://gitlab.com/demensdeum/FlameSteelEngineGameToolkitFSGL
    https://gitlab.com/demensdeum/FSGL
    https://gitlab.com/demensdeum/cube-art-project

    これらすべてを app/jni にアップロードし、各「モジュール」を別のフォルダー (例: app/jni/FSGL) にアップロードします。次に、Application.mk および Android.mk ファイルの動作するジェネレーターを見つけるオプションがあります。私はそれらを見つけられませんでしたが、おそらく CMake に基づく簡単な解決策があるでしょう。リンクをクリックして、Android NDK のアセンブリ ファイル形式について学び始めてください。
    https://developer.android.com/ndk/guides/application_mk
    https://developer.android.com/ndk/guides/android_mk

    NDK のさまざまな APP_STL 実装についてもお読みください。
    https://developer.android.com/ndk/guides/cpp-support.html

    慣れた後、「モジュール」ごとに Android.mk ファイルを作成し、続いて共有ライブラリ Cube-Art-Project のサンプル アセンブリ ファイルを作成します。

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    APP_STL := c++_static
    APP_CPPFLAGS := -fexceptions
    LOCAL_MODULE := CubeArtProject
    LOCAL_C_INCLUDES := $(LOCAL_PATH)/src $(LOCAL_PATH)/../include $(LOCAL_PATH)/../include/FlameSteelCommonTraits/src/FlameSteelCommonTraits
    LOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)/src/
    
    define walk
    $(wildcard $(1)) $(foreach e, $(wildcard $(1)/*), $(call walk, $(e)))
    endef
    
    ALLFILES = $(call walk, $(LOCAL_PATH)/src)
    FILE_LIST := $(filter %.cpp, $(ALLFILES))
    $(info CubeArtProject source code files list)
    $(info $(FILE_LIST))
    LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
    
    LOCAL_SHARED_LIBRARIES += FlameSteelCore
    LOCAL_SHARED_LIBRARIES += FlameSteelBattleHorn
    LOCAL_SHARED_LIBRARIES += FlameSteelCommonTraits
    LOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkit
    LOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkitFSGL
    LOCAL_SHARED_LIBRARIES += FSGL
    LOCAL_SHARED_LIBRARIES += SDL2
    LOCAL_SHARED_LIBRARIES += SDL2_image
    
    LOCAL_LDFLAGS := -static-libstdc++
    include $(BUILD_SHARED_LIBRARY)
    
    

    経験豊富な CMake ユーザーなら最初の行からこの構成を理解できるでしょう。形式は非常に似ており、Android.mk には GLOB_RECURSIVE がないため、walk 関数を使用してソース ファイルを再帰的に検索する必要があります。

    C コードではなく C++ をビルドするために Application.mk、Android.mk を変更します。

    APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
    APP_PLATFORM=android-16
    APP_STL := c++_static
    APP_CPPFLAGS := -fexceptions
    
    

    YourSourceHere.c -> YourSourceHere.cpp の名前を変更し、エントリを grep し、アセンブリ内のパスを変更します。

    app/jni/src/Android.mk:LOCAL_SRC_FILES := YourSourceHere.cpp
    
    

    次に、プロジェクトをビルドしてみます。ヘッダーがないことに関するコンパイラーからのエラーが表示された場合は、Android.mk 内のパスが正しいことを確認してください。 「未定義の参照」などのリンカーからのエラーがある場合は、アセンブリ内のソース コード ファイルが正しく指定されていることを確認してください。リストは、Android.mk ファイルで $(info $(FILE_LIST)) を指定することで追跡できます。 LOCAL_SHARED_LIBRARIES キーのモジュールを使用し、FSGL などの LD を介して正しいリンクを使用する、二重リンク メカニズムを忘れないでください。

    LOCAL_LDLIBS := -lEGL -lGLESv2
    
    

    適応と発売

    いくつかの点を変更する必要がありました。たとえば、iOS および Android のビルドから GLEW を削除し、一部の OpenGL 呼び出しの名前を変更し、EOS ポストフィックス (glGenVertexArrays -> glGenVertexArraysOES) を追加し、欠落している最新のデバッグ関数用のマクロを追加しました。おまけに、マクロを示す GLES2 ヘッダーが暗黙的に組み込まれていることです。 GL_GLEXT_PROTOTYPES 1:

    #define GL_GLEXT_PROTOTYPES 1
    #include "SDL_opengles2.h"
    
    

    また、最初の起動時に黒い画面が表示され、「E/libEGL: validate_display:255 error 3008 (EGL_BAD_DISPLAY)」のようなエラーが表示され、SDL ウィンドウの初期化、OpenGL プロファイルが変更され、すべてが機能しました。

    SDL_DisplayMode mode;
    SDL_GetDisplayMode(0,0,&mode);
    int width = mode.w;
    int height = mode.h;
    
    window = SDL_CreateWindow(
                title,
                0,
                0,
                width,
                height,
                SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE
            );
    
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
    

    エミュレータでは、アプリケーションはデフォルトで SDL アイコンと「Game」という名前でインストールされます。

    CMake に基づいてアセンブリ ファイルを自動的に生成するか、すべてのプラットフォームのアセンブリを Gradle に移行する可能性を検討する必要があります。ただし、CMake は現在進行中の C++ 開発における事実上の選択肢であり続けています。

    ソースコード

    https://gitlab.com/demensdeum/android- sdl-テスト-アプリ
    https://gitlab.com/demensdeum/android-sdl-test-app/tree/master/cube-art-project-android

    ソース

    https://developer.android.com/ ndk/guides/cpp-support.html
    https://developer.android.com/ndk/guides/application_mk
    https://developer.android.com/ndk/guides/android_mk
    https://lazyfoo.net/tutorials/SDL/52_hello_mobile/android_windows/index.php
    https://medium.com/androiddevelopers/getting-started-with-c-and-android-native-activities-2213b402ffff

    Leave a Comment

    Your email address will not be published. Required fields are marked *