2024/04/05(金) [n年前の日記]
#1 [prog] 自作スクリーンセーバをLinuxに対応させたい。その2
C++とOpenGLを使った自作スクリーンセーバをLinuxにも対応させようとしているところ。GLFWを使ったデモプログラムとして動かすつもり。
_mieki256/ssp3droadgl
Ubuntu Linux 22.04 LTS (g++ 11.4.0, ld 2.38)上でビルドしようとしたらリンクエラーが出てしまって悩んでしまったけれど。ソースコードに手を入れたら改善した。実行バイナリに埋め込んだpngやjpgを展開させる際、サイズの求め方を変えてみたらエラーが出ない状態になった。
ざっくり説明。
画像バイナリ(.png .jpg)を実行バイナリに含める方法は色々あるけど、今回は ld を使ってバイナリファイルをオブジェクトファイルに変換する方法を選んだ。
こうしてできたオブジェクトファイルをリンクしてやることで、実行バイナリの中に画像バイナリを含めることができる。
バイナリファイルを ld でオブジェクトファイルに変換すると、*_start, *_end, *_size の3つのシンボルを、C/C++側から参照できる状態になる。
以下は objdump -x を使って、オブジェクトファイルに含まれている情報をダンプしてみた例。「SYMBOL TABLE:」で、3つのシンボルが ―― *_end、*_size、*_start が並んでることが分かる。
C/C++側からこれらのシンボルを利用したい時は、以下のように書いておく。これで各シンボルが参照できるようになる。
このシンボルを利用して、実行バイナリ内の画像バイナリの展開処理を行うわけだけど…。今までは *_size を使って処理してた(つもりだった)。
これを、end - start でサイズを求めるように修正してみた。
このように書き換えてみたところ、エラーが出なくなってビルドが通るようになった。実行バイナリも期待した通りに動作してくれた。
また、この書き換えをしたことで、Ubuntu Linux 20.04 LTS上で発生していた不具合も ―― テクスチャの展開が時々失敗する問題も何故か解決してしまった。何度試しても、必ず展開できる…。もしかして今までは、サイズが不定値になっていたのだろうか…?
_mieki256/ssp3droadgl
Ubuntu Linux 22.04 LTS (g++ 11.4.0, ld 2.38)上でビルドしようとしたらリンクエラーが出てしまって悩んでしまったけれど。ソースコードに手を入れたら改善した。実行バイナリに埋め込んだpngやjpgを展開させる際、サイズの求め方を変えてみたらエラーが出ない状態になった。
ざっくり説明。
画像バイナリ(.png .jpg)を実行バイナリに含める方法は色々あるけど、今回は ld を使ってバイナリファイルをオブジェクトファイルに変換する方法を選んだ。
$ ld -r -b binary -o sprites.o sprites.png
こうしてできたオブジェクトファイルをリンクしてやることで、実行バイナリの中に画像バイナリを含めることができる。
バイナリファイルを ld でオブジェクトファイルに変換すると、*_start, *_end, *_size の3つのシンボルを、C/C++側から参照できる状態になる。
以下は objdump -x を使って、オブジェクトファイルに含まれている情報をダンプしてみた例。「SYMBOL TABLE:」で、3つのシンボルが ―― *_end、*_size、*_start が並んでることが分かる。
$ ld -r -b binary -o sprites.o sprites.png $ objdump -x sprites.o sprites.o: ファイル形式 elf64-x86-64 sprites.o アーキテクチャ: i386:x86-64, フラグ 0x00000010: HAS_SYMS 開始アドレス 0x0000000000000000 セクション: Idx Name Size VMA LMA File off Algn 0 .data 00875cae 0000000000000000 0000000000000000 00000040 2**0 CONTENTS, ALLOC, LOAD, DATA SYMBOL TABLE: 0000000000000000 l d .data 0000000000000000 .data 0000000000875cae g .data 0000000000000000 _binary_sprites_png_end 0000000000875cae g *ABS* 0000000000000000 _binary_sprites_png_size 0000000000000000 g .data 0000000000000000 _binary_sprites_png_start
C/C++側からこれらのシンボルを利用したい時は、以下のように書いておく。これで各シンボルが参照できるようになる。
extern unsigned char _binary_sprites_png_start; // binary start address extern unsigned char _binary_sprites_png_end; // binary end address extern unsigned char _binary_sprites_png_size; // binary size
このシンボルを利用して、実行バイナリ内の画像バイナリの展開処理を行うわけだけど…。今までは *_size を使って処理してた(つもりだった)。
img_ptr = &_binary_sprites_png_start; // start address img_size = (size_t)&_binary_sprites_png_size; // size gw.spr_tex = createTextureFromMemory(img_ptr, img_size);
これを、end - start でサイズを求めるように修正してみた。
img_ptr = &_binary_sprites_png_start; // start address img_size = (size_t)((&_binary_sprites_png_end) - (&_binary_sprites_png_start)); // size gw.spr_tex = createTextureFromMemory(img_ptr, img_size);
このように書き換えてみたところ、エラーが出なくなってビルドが通るようになった。実行バイナリも期待した通りに動作してくれた。
また、この書き換えをしたことで、Ubuntu Linux 20.04 LTS上で発生していた不具合も ―― テクスチャの展開が時々失敗する問題も何故か解決してしまった。何度試しても、必ず展開できる…。もしかして今までは、サイズが不定値になっていたのだろうか…?
[ ツッコむ ]
以上です。