lovyan03 / LovyanGFX

SPI LCD graphics library for ESP32 (ESP-IDF/ArduinoESP32) / ESP8266 (ArduinoESP8266) / SAMD51(Seeed ArduinoSAMD51)
Other
1.03k stars 189 forks source link

0.3.2から #include<LovyanGFX.h>の解釈経路が異なる場合がある #82

Closed GOB52 closed 3 years ago

GOB52 commented 3 years ago

LovyanGFX 0.3.0/0.3.2 Arduino M5Stack Grey.

include を #include の前に入れるか入れないかでの経路が 0.3.2 から変わったようです。

0.3.0 までは同経路の解釈をしていると思われます。

LGFX_Sprite.hpp の 150行目付近の createFromBmp付近の分岐に #pragma messageを仕込んだ結果は以下の通りです。

0.3.2以降は必ず #include すべきでしょうか?

scratch.ino

#include <M5Stack.h>
#include <LovyanGFX.h>

test.cpp

#include <LovyanGFX.h>

Ver 0.3.0 .ino/.cpp 同経路

In file included from /Users/gob/projects/M5Stack/libraries/LovyanGFX/src/LovyanGFX.hpp:43:0,
                 from /Users/gob/projects/M5Stack/libraries/LovyanGFX/src/LovyanGFX.h:5,
                 from /Users/gob/tmp/sketch/test.cpp:1:
/Users/gob/projects/M5Stack/libraries/LovyanGFX/src/lgfx/LGFX_Sprite.hpp:151:35: note: #pragma message: FS_H/SEEED_FS
    #pragma message("FS_H/SEEED_FS")
                                   ^
In file included from /Users/gob/projects/M5Stack/libraries/LovyanGFX/src/LovyanGFX.hpp:43:0,
                 from /Users/gob/projects/M5Stack/libraries/LovyanGFX/src/LovyanGFX.h:5,
                 from /Users/gob/projects/M5Stack/scratch/scratch.ino:7:
/Users/gob/projects/M5Stack/libraries/LovyanGFX/src/lgfx/LGFX_Sprite.hpp:151:32: note: #pragma message: FS_H/SEEED_FS
    #pragma message("FS_H/SEEED_FS")

Ver 0.3.2 .ino/.cpp 違経路

In file included from /Users/gob/projects/M5Stack/libraries/LovyanGFX/src/LovyanGFX.hpp:43:0,
                 from /Users/gob/projects/M5Stack/libraries/LovyanGFX/src/LovyanGFX.h:5,
                 from /Users/gob/projects/M5Stack/scratch/scratch.ino:7:
/Users/gob/projects/M5Stack/libraries/LovyanGFX/src/lgfx/LGFX_Sprite.hpp:151:32: note: #pragma message: FS_H/SEEED_FS
   #pragma message("FS_H/SEEED_FS")
lovyan03 commented 3 years ago

LovyanGFXでファイルシステム関連の機能を有効にしたい場合は、LovyanGFXより先にincludeをしておく必要があります。

#include <SD.h>          // SDを使いたい場合
#include <SPIFFS.h>      // SPIFFSを使いたい場合
#include <LovyanGFX.hpp> // 最後にLovyanGFXをincludeする

M5Stack.hにはSD.hのincludeが含まれているので、上記のSD.hをincludeするのと同様の効果があります。

何故こんなことになっているかというと… 描画ライブラリがファイルシステム(SD.h/SPIFFS.h等)に依存されると困る、という利用シーンがあるため、 "LovyanGFXより前にincludeされている場合に限り、FS関連機能をifdefで追加する" という方法にしたのです。 ご指摘の 0.3.2 より前のバージョンでは、 FS.h だけはincludeしていたのですが、 ArduinoESP32とは別のファイルシステムを使おうとした場合に FS.h が衝突を起こしたため、 このincludeも廃止する事にしました。

LovyanGFX内ではFS関連のincludeを書きたくないが、FS関連の機能は提供したい。 これをうまく解決する実装方法が他にないか…アイデア募集中です…

GOB52 commented 3 years ago

なるほどそういう経緯でしたか。

解決案としては ファイルシステム依存する部分はLGFX_Sprite自体のメソッドとして持たずに別クラス(friend classとする)、別ファイルとして分離 (SD用[A]、SPIFFS用[B]それぞれ) し LovyanGFX.h 内には含めない。 利用者側が明示的に A or B をインクルードして使用とかどうでしょ?

lovyan03 commented 3 years ago

@GOB52 やはりそういう形が素直になりますよね…。 ちゃんと分離するなら別クラスにすべき内容だとは思うのですが、出来ればLGFXのメソッドとして提供したい…と思っていまして…うむむ…。 ちなみに基底クラスの方にある drawJpgFile等のメソッドはファイルを分けて lgfx_filesystem_support.hpp にまとめています。(ちょっと奇抜な方法で有効化しています…)

GOB52 commented 3 years ago

includeの仕方によらず型の情報が矛盾しないようにするためには別にする位しかないような気もします。

発端は自プロジェクトでのLovyanGFXのバージョンを0.2.7から0.3.4に上げた際に発生したクラッシュでした。(LGFX_Spriteのメソッド呼び出しで発生) そこから発生バージョンの検証、再現するミニマムなコードの作成と検証を経て気がついた次第です。

メソッドとして提供を満たした上で型情報矛盾を起こさないような方策を、こちらでも研究してみますね。

lovyan03 commented 3 years ago

あぁ…そちらでも問題が発生してしまいましたか…。 LovyanGFX型の形がコンパイル単位で異なってしまうために、 派生クラスのLGFX_Spriteも その影響を受けてしまうのです…ね…。 致命的な問題であるとは認識しているのですが…さてどうしましょうか…

lovyan03 commented 3 years ago

@GOB52 developブランチを更新してみました。 従来はメンバとしてFileWrapperのインスタンスを保持していたのですが、これがヘッダのinclude状況によってインスタンスのサイズが変化してしまう原因になっていたので、ポインタの形でLGFXBaseクラスに持たせるようにしてみました。 とりあえずは これでコンパイル単位でインスタンスの形が異なってしまうという状況は避けられるのではないか…と…思います…。

GOB52 commented 3 years ago

@lovyan03

develop版試してみました。 当方のクラッシュは起こらなくなりました。

が、依然経路の違いでLGFX_SpriteにcreateFromBmpFileを持った物と持っていない物の混在が生じます。 class内部のメソッドテーブルの相違によって予期せぬ挙動を引き起こしたりしませんかね? 仮想関数(vtable)ではないので大丈夫なのかしら。 C++詳細仕様にそこまで詳しくないのでにんともかんとも。

lovyan03 commented 3 years ago

はい、それに関しては確かに依然としてコンパイル単位でメソッドの有無が異なるという状態にはなりますが、リンカが調整してくれる部分なので大丈夫なはずです。

なお根本的な問題として「include順に依存して変化するクラス」というのがアウトという意見もあります… ツライ…(:3 」∠)

GOB52 commented 3 years ago

なるほど、その辺りの解決はうまくやってくれるんですね。

なお根本的な問題として「include順に依存して変化するクラス」というのがアウトという意見もあります…

エレガントな解法はないものかなぁ。

lovyan03 commented 3 years ago

そうですね…引数にSDやSPIFFSを要求する関数があるので難しいんですよね… (M5DisplayやTFT_eSPIで実装されてるメソッドと同じものをLovyanGFXでも提供しようとしているため)

「LovyanGFX内ではSDやSPIFFSをincludeさせたくない」 「しかしSDやSPIFFSを引数に受け取るメソッドは提供したい」 要求自体が矛盾しているんですよね(汗

lovyan03 commented 3 years ago

@GOB52 この問題の修正を含む新しいリリース ver0.3.5を作成しました。 お時間あるときにお試し頂ければ幸いです。 よろしくお願いいたします~。

GOB52 commented 3 years ago

@lovyan03 当方のプロジェクトにおけるハングが 0.3.5 にて解消されたことを確認いたしました。 リンクエラーの件でお騒がせしてすいません。 対応ありがとうございました!