{"id":2502,"date":"2020-01-12T11:47:43","date_gmt":"2020-01-12T08:47:43","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=2502"},"modified":"2024-12-16T22:32:30","modified_gmt":"2024-12-16T19:32:30","slug":"porting-cpp-sdl-app-on-android","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/de\/2020\/01\/12\/porting-cpp-sdl-app-on-android\/","title":{"rendered":"Portieren einer C++-SDL-Anwendung auf Android"},"content":{"rendered":"<p>In diesem Beitrag beschreibe ich meine Erfahrungen mit der Portierung eines Prototyps eines 3D-Editors <a href=\"https:\/\/gitlab.com\/demensdeum\/cube-art-project-bootstrap\" target=\"_blank\" rel=\" noopener noreferrer\">Cube Art Project<\/a>auf Android.<br \/>Schauen wir uns zun\u00e4chst das Ergebnis an: Im Emulator l\u00e4uft ein Editor mit einem roten 3D-W\u00fcrfelcursor:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-2509\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2020\/01\/emulator.png\" alt=\"\" width=\"460\" height=\"265\" srcset=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2020\/01\/emulator.png 959w, https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2020\/01\/emulator-300x173.png 300w, https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2020\/01\/emulator-768x442.png 768w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><\/p>\n<p>F\u00fcr eine erfolgreiche Montage mussten Sie Folgendes tun:<\/p>\n<ol>\n<li>Installieren Sie das neueste Android SDK und NDK (je neuer die NDK-Version, desto besser).<\/li>\n<li>Laden Sie den SDL2-Quellcode herunter und verwenden Sie die Vorlage von dort, um die Android-Anwendung zu erstellen.<\/li>\n<li>SDL Image und SDL Mixer zur Baugruppe hinzuf\u00fcgen.<\/li>\n<li>F\u00fcgen Sie die Bibliotheken meiner Spiel-Engine und meines Toolkits sowie deren Abh\u00e4ngigkeiten hinzu (GLM, JSON f\u00fcr Modern C++)<\/li>\n<li>Assembly-Dateien f\u00fcr Gradle anpassen.<\/li>\n<li>C++-Code f\u00fcr Kompatibilit\u00e4t mit Android anpassen, betroffene plattformabh\u00e4ngige Komponenten \u00e4ndern (OpenGL ES, Grafikkontextinitialisierung)<\/li>\n<li>Erstellen und testen Sie das Projekt auf dem Emulator.<\/li>\n<\/ol>\n<h3>Projektvorlage<\/h3>\n<p>Laden der Quellen SDL, SDL Image, SDL Mixer:<br \/><a href=\"https:\/\/www.libsdl.org\/download-2.0.php\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.libsdl.org\/download-2.0.php<\/a><br \/>\nDer Ordner \u201edocs\u201c enth\u00e4lt detaillierte Anweisungen zum Arbeiten mit der Android-Projektvorlage. Kopieren Sie das Android-Projektverzeichnis in einen separaten Ordner, erstellen Sie einen Symlink oder kopieren Sie den SDL-Ordner nach Android-Projekt\/App\/jni.<br \/>Wir ersetzen das Avd-Flag durch die richtige Kennung und starten den Android-Emulator aus dem Verzeichnis Sdk:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>cd ~\/Android\/Sdk\/emulator\n.\/emulator -avd Pixel_2_API_24\n\n<\/code><\/pre>\n<\/div>\n<p>Geben Sie die Pfade im Skript an und stellen Sie das Projekt zusammen:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>rm -rf app\/build || true\nexport ANDROID_HOME=\/home\/demensdeum\/Android\/Sdk\/\nexport ANDROID_NDK_HOME=\/home\/demensdeum\/Android\/android-ndk-r21-beta2\/\n.\/gradlew clean build\n.\/gradlew installDebug\n\n<\/code><\/pre>\n<\/div>\n<p>Die SDL-Projektvorlage mit C-Code aus der Datei sollte zusammengestellt werden<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>android-sdl-test-app\/cube-art-project-android\/app\/jni\/src\/YourSourceHere.c\n\n<\/code><\/pre>\n<\/div>\n<h3>Abh\u00e4ngigkeiten<\/h3>\n<p>Laden Sie den Quellcode in den Archiven f\u00fcr SDL_image und SDL_mixer herunter:<br \/><a href=\"https:\/\/www.libsdl.org\/projects\/SDL_image\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.libsdl.org\/projects\/SDL_image\/<\/a><br \/>\n<a href=\"https:\/\/www.libsdl.org\/projects\/SDL_mixer\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.libsdl.org\/projects\/SDL_mixer\/<\/a><\/p>\n<p>Laden der Abh\u00e4ngigkeiten Ihres Projekts, zum Beispiel meiner gemeinsam genutzten Bibliotheken:<br \/><a href=\"https:\/\/gitlab.com\/demensdeum\/FlameSteelCore\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/FlameSteelCore\/<\/a><br \/>\n<a href=\"https:\/\/gitlab.com\/demensdeum\/FlameSteelCommonTraits\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/FlameSteelCommonTraits<\/a><br \/>\n<a href=\"https:\/\/gitlab.com\/demensdeum\/FlameSteelBattleHorn\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/FlameSteelBattleHorn<\/a><br \/>\n<a href=\"https:\/\/gitlab.com\/demensdeum\/FlameSteelEngineGameToolkit\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/FlameSteelEngineGameToolkit\/<\/a><br \/>\n<a href=\"https:\/\/gitlab.com\/demensdeum\/FlameSteelEngineGameToolkitFSGL\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/FlameSteelEngineGameToolkitFSGL<\/a><br \/>\n<a href=\"https:\/\/gitlab.com\/demensdeum\/FSGL\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/FSGL<\/a><br \/>\n<a href=\"https:\/\/gitlab.com\/demensdeum\/cube-art-project\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/cube-art-project<\/a><\/p>\n<p>Wir laden das alles nach app\/jni hoch, jedes \u201eModul\u201c in einen separaten Ordner, zum Beispiel app\/jni\/FSGL. Als n\u00e4chstes haben Sie die M\u00f6glichkeit, funktionierende Generatoren f\u00fcr die Dateien Application.mk und Android.mk zu finden. Ich habe sie nicht gefunden, aber vielleicht gibt es eine einfache L\u00f6sung, die auf CMake basiert. Folgen Sie den Links und machen Sie sich mit dem Assembly-Dateiformat f\u00fcr Android NDK vertraut:<br \/><a href=\"https:\/\/developer.android.com\/ndk\/guides\/application_mk\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/ndk\/guides\/application_mk<\/a><br \/>\n<a href=\"https:\/\/developer.android.com\/ndk\/guides\/android_mk\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/ndk\/guides\/android_mk<\/a><\/p>\n<p>Sie sollten auch \u00fcber verschiedene APP_STL-Implementierungen in NDK lesen:<br \/><a href=\"https:\/\/developer.android.com\/ndk\/guides\/cpp-support.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/ndk\/guides\/cpp-support.html<\/a><\/p>\n<p>Nach der Einarbeitung erstellen wir f\u00fcr jedes \u201eModul\u201c eine Android.mk-Datei, gefolgt von einer Beispiel-Assembly-Datei der gemeinsam genutzten Bibliothek Cube-Art-Project:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>LOCAL_PATH := $(call my-dir)\ninclude $(CLEAR_VARS)\n\nAPP_STL := c++_static\nAPP_CPPFLAGS := -fexceptions\nLOCAL_MODULE := CubeArtProject\nLOCAL_C_INCLUDES := $(LOCAL_PATH)\/src $(LOCAL_PATH)\/..\/include $(LOCAL_PATH)\/..\/include\/FlameSteelCommonTraits\/src\/FlameSteelCommonTraits\nLOCAL_EXPORT_C_INCLUDES = $(LOCAL_PATH)\/src\/\n\ndefine walk\n$(wildcard $(1)) $(foreach e, $(wildcard $(1)\/*), $(call walk, $(e)))\nendef\n\nALLFILES = $(call walk, $(LOCAL_PATH)\/src)\nFILE_LIST := $(filter %.cpp, $(ALLFILES))\n$(info CubeArtProject source code files list)\n$(info $(FILE_LIST))\nLOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)\/%=%)\n\nLOCAL_SHARED_LIBRARIES += FlameSteelCore\nLOCAL_SHARED_LIBRARIES += FlameSteelBattleHorn\nLOCAL_SHARED_LIBRARIES += FlameSteelCommonTraits\nLOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkit\nLOCAL_SHARED_LIBRARIES += FlameSteelEngineGameToolkitFSGL\nLOCAL_SHARED_LIBRARIES += FSGL\nLOCAL_SHARED_LIBRARIES += SDL2\nLOCAL_SHARED_LIBRARIES += SDL2_image\n\nLOCAL_LDFLAGS := -static-libstdc++\ninclude $(BUILD_SHARED_LIBRARY)\n\n<\/code><\/pre>\n<\/div>\n<p>Jeder erfahrene CMake-Benutzer wird diese Konfiguration von den ersten Zeilen an verstehen, die Formate sind sehr \u00e4hnlich, Android.mk fehlt GLOB_RECURSIVE, sodass Sie mit der Walk-Funktion rekursiv nach Quelldateien suchen m\u00fcssen.<\/p>\n<p>Wir \u00e4ndern Application.mk und Android.mk, um C++ und nicht C-Code zu erstellen:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>APP_ABI := armeabi-v7a arm64-v8a x86 x86_64\nAPP_PLATFORM=android-16\nAPP_STL := c++_static\nAPP_CPPFLAGS := -fexceptions\n\n<\/code><\/pre>\n<\/div>\n<p>Benennen Sie YourSourceHere.c -> YourSourceHere.cpp um, \u00fcberpr\u00fcfen Sie die Eintr\u00e4ge, \u00e4ndern Sie den Pfad in der Assembly, zum Beispiel:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>app\/jni\/src\/Android.mk:LOCAL_SRC_FILES := YourSourceHere.cpp\n\n<\/code><\/pre>\n<\/div>\n<p>Versuchen Sie als N\u00e4chstes, das Projekt zu erstellen. Wenn Sie vom Compiler Fehlermeldungen \u00fcber das Fehlen von Headern sehen, \u00fcberpr\u00fcfen Sie die Richtigkeit der Pfade in Android.mk. Wenn vom Linker Fehler wie \u201eundefinierte Referenz\u201c auftreten, \u00fcberpr\u00fcfen Sie, ob die Quellcodedateien in den Assemblys korrekt angegeben sind, indem Sie $(info $(FILE_LIST)) in der Datei Android.mk angeben. Vergessen Sie nicht den doppelten Verkn\u00fcpfungsmechanismus, die Verwendung von Modulen im Schl\u00fcssel LOCAL_SHARED_LIBRARIES und die korrekte Verkn\u00fcpfung \u00fcber LD, zum Beispiel f\u00fcr FSGL:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>LOCAL_LDLIBS := -lEGL -lGLESv2\n\n<\/code><\/pre>\n<\/div>\n<h3>Anpassung und Einf\u00fchrung<\/h3>\n<p>Ich musste einige Dinge \u00e4ndern, zum Beispiel GLEW aus den Builds f\u00fcr iOS und Android entfernen, einige der OpenGL-Aufrufe umbenennen, das EOS-Postfix hinzuf\u00fcgen (glGenVertexArrays -> glGenVertexArraysOES) und ein Makro f\u00fcr die fehlenden modernen Debugging-Funktionen einf\u00fcgen , das Sahneh\u00e4ubchen ist die implizite Einbindung von GLES2-Headern, die auf Makros hinweisen GL_GLEXT_PROTOTYPES 1:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>#define GL_GLEXT_PROTOTYPES 1\n#include \"SDL_opengles2.h\"\n\n<\/code><\/pre>\n<\/div>\n<p>Ich habe bei den ersten Starts auch einen schwarzen Bildschirm mit einem Fehler wie \u201eE\/libEGL: validate_display:255 error 3008 (EGL_BAD_DISPLAY)\u201c beobachtet, die Initialisierung des SDL-Fensters und des OpenGL-Profils ge\u00e4ndert und alles hat funktioniert:<\/p >\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>SDL_DisplayMode mode;\nSDL_GetDisplayMode(0,0,&mode);\nint width = mode.w;\nint height = mode.h;\n\nwindow = SDL_CreateWindow(\n            title,\n            0,\n            0,\n            width,\n            height,\n            SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE\n        );\n\nSDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );\n<\/code><\/pre>\n<\/div>\n<p>Auf dem Emulator wird die Anwendung standardm\u00e4\u00dfig mit dem SDL-Symbol und dem Namen \u201eSpiel\u201c installiert.<\/p>\n<p>Ich muss nur die M\u00f6glichkeit erkunden, Assembly-Dateien automatisch auf Basis von CMake zu generieren oder Assemblys f\u00fcr alle Plattformen nach Gradle zu migrieren; CMake bleibt jedoch de facto die Wahl f\u00fcr die fortlaufende C++-Entwicklung.<\/p>\n<h3>Quellcode<\/h3>\n<p><a href=\"https:\/\/gitlab.com\/demensdeum\/android-sdl-test-app\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/android- SDL-Test-App<\/a><br \/><a href=\"https:\/\/gitlab.com\/demensdeum\/android-sdl-test-app\/tree\/master\/cube-art-project-android\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/android-sdl-test-app\/tree\/master\/cube-art-project-android<\/a><\/p>\n<h3>Quellen<\/h3>\n<p><a href=\"https:\/\/developer.android.com\/ndk\/guides\/cpp-support.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/ ndk\/guides\/cpp-support.html<\/a><br \/><a href=\"https:\/\/developer.android.com\/ndk\/guides\/application_mk\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/ndk\/guides\/application_mk<\/a><br \/>\n<a href=\"https:\/\/developer.android.com\/ndk\/guides\/android_mk\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/developer.android.com\/ndk\/guides\/android_mk<\/a><br \/>\n<a href=\"https:\/\/lazyfoo.net\/tutorials\/SDL\/52_hello_mobile\/android_windows\/index.php\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/lazyfoo.net\/tutorials\/SDL\/52_hello_mobile\/android_windows\/index.php<\/a><br \/>\n<a href=\"https:\/\/medium.com\/androiddevelopers\/getting-started-with-c-and-android-native-activities-2213b402ffff\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/medium.com\/androiddevelopers\/getting-started-with-c-and-android-native-activities-2213b402ffff<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In diesem Beitrag beschreibe ich meine Erfahrungen mit der Portierung eines Prototyps eines 3D-Editors Cube Art Projectauf Android.Schauen wir uns zun\u00e4chst das Ergebnis an: Im Emulator l\u00e4uft ein Editor mit einem roten 3D-W\u00fcrfelcursor: F\u00fcr eine erfolgreiche Montage mussten Sie Folgendes tun: Installieren Sie das neueste Android SDK und NDK (je neuer die NDK-Version, desto besser).<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/de\/2020\/01\/12\/porting-cpp-sdl-app-on-android\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Portieren einer C++-SDL-Anwendung auf Android&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,52],"tags":[37,124,145,146,77,147,148],"class_list":["post-2502","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-android","tag-c","tag-cpp","tag-opengl-es","tag-sdl","tag-sdl-image","tag-sdl-mixer","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"de","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/2502","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/comments?post=2502"}],"version-history":[{"count":31,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/2502\/revisions"}],"predecessor-version":[{"id":3923,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/posts\/2502\/revisions\/3923"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/media?parent=2502"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/categories?post=2502"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/de\/wp-json\/wp\/v2\/tags?post=2502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}