D言語とDxLibでAndroid上にD言語くんを出現させる
旧暦ですら2021年を迎えてしまいましたが
AndroidでD言語でDXライブラリを使ってD言語くんを降臨させました
この記事はリンク先の記事にインスパイアされています
なお世界に同じ環境でやる人がいるか微妙ですがLinux上(Xubuntu 20.04)で開発しています
Android Studioの準備
公式ページから落として
公式ガイドに従って入れるだけですね
依存ライブラリなしで動きましたが気になる人は入れたほうが無難かと思います
LDCの準備
公式のreleaseページから各ファイルをダウンロード
執筆時点では1.25.0を使いました(ちんたら執筆してたら正式版が出た)
- ldc2-1.25.0-linux-x86_64.tar.xz (コンパイラ)
- ldc2-1.25.0-android-aarch64.tar.xz (x86_64/aarch64向けライブラリ)
- ldc2-1.25.0-android-armv7a.tar.xz (i686/armv7a向けライブラリ)
ダウンロードして展開して中身を使いやすいように移動
export LDC2VER=1.25.0
wget https://github.com/ldc-developers/ldc/releases/download/v$LDC2VER/ldc2-$LDC2VER-linux-x86_64.tar.xz
wget https://github.com/ldc-developers/ldc/releases/download/v$LDC2VER/ldc2-$LDC2VER-android-aarch64.tar.xz
wget https://github.com/ldc-developers/ldc/releases/download/v$LDC2VER/ldc2-$LDC2VER-android-armv7a.tar.xz
tar xf ldc2-$LDC2VER-linux-x86_64.tar.xz
tar xf ldc2-$LDC2VER-android-aarch64.tar.xz
tar xf ldc2-$LDC2VER-android-armv7a.tar.xz
mv ldc2-$LDC2VER-android-aarch64/lib-x86_64 ldc2-$LDC2VER-linux-x86_64/lib-android_x86_64
mv ldc2-$LDC2VER-android-aarch64/lib ldc2-$LDC2VER-linux-x86_64/lib-android_arm64-v8a
mv ldc2-$LDC2VER-android-armv7a/lib-i686 ldc2-$LDC2VER-linux-x86_64/lib-android_x86
mv ldc2-$LDC2VER-android-armv7a/lib ldc2-$LDC2VER-linux-x86_64/lib-android_armeabi-v7a
ここまでやったらldcを適当にPATHに通しておいてください
export PATH=$PATH:path/to/ldc2-$LDC2VER-linux-x86_64/bin
#例: echo "export PATH=\$PATH:`pwd`/ldc2-$LDC2VER-linux-x86_64/bin" >> ~/.bashrc ; source ~/.bashrc
続いてldc2.confを修正しますが、NDKパスを確定させたいので次章の「Android StudioでDxLibを使う」
を先に読んでNDKのインストールを行ってパスを確認してください
NDKのパスがわかったらldc2.confを修正します
NDKPATH=path-to-ndk-toolchain
#例: NDKPATH=$HOME/Android/Sdk/ndk/21.1.6352462
cat >> ldc2-$LDC2VER-linux-x86_64/etc/ldc2.conf << EOF
"x86_64-.*-linux-android":
{
switches = [
"-defaultlib=phobos2-ldc,druntime-ldc",
"-link-defaultlib-shared=false",
"-gcc=${NDKPATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android21-clang",
];
lib-dirs = [
"%%ldcbinarypath%%/../lib-android_x86_64",
];
rpath = "";
};
"i686-.*-linux-android":
{
switches = [
"-defaultlib=phobos2-ldc,druntime-ldc",
"-link-defaultlib-shared=false",
"-gcc=${NDKPATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android21-clang",
];
lib-dirs = [
"%%ldcbinarypath%%/../lib-android_x86",
];
rpath = "";
};
"aarch64-.*-linux-android":
{
switches = [
"-defaultlib=phobos2-ldc,druntime-ldc",
"-link-defaultlib-shared=false",
"-gcc=${NDKPATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang",
];
lib-dirs = [
"%%ldcbinarypath%%/../lib-android_arm64-v8a",
];
rpath = "";
};
"armv7a-.*-linux-android":
{
switches = [
"-defaultlib=phobos2-ldc,druntime-ldc",
"-link-defaultlib-shared=false",
"-gcc=${NDKPATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang",
];
lib-dirs = [
"%%ldcbinarypath%%/../lib-android_armeabi-v7a",
];
rpath = "";
};
EOF
Android StudioでDxLibを使う
公式ガイドに従って入れますが
Linuxだとzipが文字化けするので少し注意が必要です
$ unzip -l -O cp932 DxLib_Android3_22a.zip # 確認したければ
$ unzip -O cp932 DxLib_Android3_22a.zip
なお-O CHARSET
オプションはディストリビューションによってはなかったり(Arch Linuxとか)するので
その時はがんばってください
2章が終わってNDKが入ったら前章のNDKの設定をldc2.confに入れてください
他変更は以下
3.1
手で触りたくない人向け
cd <path-to-project> (以下同or続けて)
sed -i app/src/main/AndroidManifest.xml \
-e "s#android:theme\(.*\)>#android:theme\1#" \
-e 's# <activity android:name=".MainActivity">#\
android:hasCode="false">\n\
<activity android:name="android.app.NativeActivity">\n\
<meta-data android:name="android.app.lib_name"\n\
android:value="native-lib" />#'
3.2
手で触りたくない人向け
link_directoriesはよしなにいじってください
DXLIB_LIBPATH_PREFIX="path/to/プロジェクトに追加すべきファイル_Android用/"
PROJECT_LIBPATH_PREFIX="path/to/yourproject/app/src/main/cpp/samplelibdir/"
LDC2_LIBPATH_PREFIX="path/to/ldc2-$LDC2VER-linux-x86_64/lib-android_"
例:
DXLIB_LIBPATH_PREFIX="$HOME/Downloads/DxLib_Android/プロジェクトに追加すべきファイル_Android用/"
PROJECT_LIBPATH_PREFIX="$HOME/AndroidStudioProjects/test/app/src/main/cpp/samplelibdir/"
LDC2_LIBPATH_PREFIX="$HOME/Downloads/ldc2-$LDC2VER-linux-x86_64/lib-android_"
sed -i app/src/main/cpp/CMakeLists.txt \
-e "/^add_library/i include_directories( ${DXLIB_LIBPATH_PREFIX}\${ANDROID_ABI} )\n\
link_directories( ${DXLIB_LIBPATH_PREFIX}\${ANDROID_ABI}\n\
${PROJECT_LIBPATH_PREFIX}\${ANDROID_ABI}\n\
${LDC2_LIBPATH_PREFIX}\${ANDROID_ABI} )\n\
" \
-e "s#\${log-lib} )#`for l in {' ',\\${log-lib},\
android,GLESv1_CM,EGL,GLESv2,OpenSLES,m,sample,phobos2-ldc,druntime-ldc,DxLib,DxUseCLib,\
jpeg,png,zlib,tiff,theora_static,vorbis_static,vorbisfile_static,ogg_static,bullet,'opus )'};\
do echo -n ' '$l'\n'; done`#"
4
native-lib.cppはDのコードを呼び出す機能だけ搭載しています
cat > app/src/main/cpp/native-lib.cpp << 'EOF'
extern "C" void myDmain();
void android_main(){
myDmain();
}
EOF
Dのランタイム特有?の問題としてリンカをbfdにしてあげないとクラッシュするっぽいためbuild.gradleを変更
また、ldcのライブラリがr21のSDKでコンパイルされているため対象API Levelを21(=Android 5.0以上が必要)に設定
sed -i app/build.gradle -e 's/cppFlags ""/cppFlags "-Wl,-fuse-ld=bfd"/'
sed -i app/build.gradle -e 's/minSdkVersion 16/minSdkVersion 21/'
本体コードをDで書く
元コードからの変更は最小限にしてます
D言語バインドとして拙作のdxlib-dを使用しています
cat > app/src/main/cpp/sample.d << 'EOF'
module main;
import dxlib;
import std.string;
//import std.file;
extern(C) int __android_log_write(int, const(char)*, const(char)*);
// この辺もう少しきれいにしたい
alias extern(C) int function(char[][] args) MainFunc;
//extern(C) int _d_run_main(int argc, char** argv, MainFunc mainFunc);
extern(C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainFunc mainFunc);
extern(C) int myDmain(){
return _d_run_main2(null, 0, &myDmain2);
}
extern(C) int myDmain2(char[][] args){
main_();
return 0;
}
// mainのままだとldcがセグフォした
void main_()
{
int count, x, y;
try
{
int mHandle;
//ChangeWindowMode(TRUE);
if (DxLib_Init() < 0 )
{
throw new Exception("DXライブラリの初期化に失敗");
}
if ((mHandle = MV1LoadModel("Mr_D.pmd")) == -1)
{
throw new Exception("モデルの読み込みに失敗");
}
// なんかこう書かないとVECTORがうまく使えなかった
auto camera = VECTOR(0.0f, 10.0f, -20.0f);
auto target = VECTOR(0.0f, 10.0f, 0.0f);
SetBackgroundColor(0, 0, 255);
ClearDrawScreen();
SetCameraNearFar(1.0f, 150.0f);
SetCameraPositionAndTarget_UpVecY(camera, target);
// ここvmdファイルが必要?
/+ if (MV1AttachAnim(mHandle, 0, -1, FALSE) == -1)
{
throw new Exception("アニメーションの再生に失敗");
}
MV1SetAttachAnimTime(mHandle, 0, 0.0f); +/
if (MV1DrawModel(mHandle) == -1)
{
throw new Exception("モデルの描画に失敗");
}
WaitKey();
}
catch( Exception e )
{
//std.file.write( "error.log", e.msg );
__android_log_write(6, "d-catched", e.msg.toStringz);
//throw e;
}
finally
{
DxLib_End();
}
}
EOF
各環境用にライブラリをビルド
mkdir -p app/src/main/cpp/samplelibdir/{arm64-v8a,armeabi-v7a,x86,x86_64}
pushd app/src/main/cpp/samplelibdir/x86_64
ldc2 -mtriple=x86_64--linux-android -c ../../sample -I ~/dxlib-d/ && rm -f libsample.a && ar rcs libsample.a sample.o
popd
pushd app/src/main/cpp/samplelibdir/arm64-v8a
ldc2 -mtriple=aarch64--linux-android -c ../../sample -I ~/dxlib-d/ && rm -f libsample.a && ar rcs libsample.a sample.o
popd
pushd app/src/main/cpp/samplelibdir/x86
ldc2 -mtriple=i686--linux-android -c ../../sample -I ~/dxlib-d/ && rm -f libsample.a && ar rcs libsample.a sample.o
popd
pushd app/src/main/cpp/samplelibdir/armeabi-v7a
ldc2 -mtriple=armv7a--linux-androideabi -c ../../sample -I ~/dxlib-d/ && rm -f libsample.a && ar rcs libsample.a sample.o
popd
Androidの場合、各種追加ファイルはassetsディレクトリに配置します
mkdir -p app/src/main/assets
Mr_D.pmdをapp/src/main/assetsに配置
同じくテクスチャですがファイル名が違うようでTex_D.pngをTex_D.bmp(一応変換した)にして保存
あとはAndroid Studio上でAVD Managerから適当な(Android 5.0+必須でx86_64推奨)エミュレータを起動しつつ
Run→Run 'app'で実験(起動してるAVDと同じアーキテクチャのバイナリだけ入ってます)
問題なさそうならMake Module '〜.app'でapk(全環境用のバイナリが入ってます)ができます
native-lib.cppの機能をD側で用意してso作成してパッケージ化すればD言語(とAndroidのビルドコマンド)の知識のみでAndroidアプリ開発ができそうですね!(疲れた)
Author And Source
この問題について(D言語とDxLibでAndroid上にD言語くんを出現させる), 我々は、より多くの情報をここで見つけました https://qiita.com/dragoon2014/items/79184121b77296540da9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .