2010年8月10日火曜日

mbedのSDFileSystem(とFATFileSystem)を使おうとした時に"Expected an identifier (E40)" in file "/YourProgramName/lib/FATFileSystem/integer.h"と怒られたら

mbedには世界中の様々な人達が作った便利なライブラリが集結しています。
ですから簡単に色々な事が試せるのです。

が、「世界中の様々な人達が作っている」がために問題が露呈することもあります。
今回遭遇した問題もその類。

SDFileSystemを使おうとコーディングしてコンパイルに通すと
"Expected an identifier (E40)" in file "/YourProgramName/lib/FATFileSystem/integer.h" (Line: 27, Col: 15)
と怒られてしまいました。

「他に困っている人はいないかな?」とmbedのフォーラムを調べてみると、やっぱりいます。
Forum ≫ mbed ≫ Expected an identifier (E40)
しかも、投稿者は有力な回答が得られないままになっている様子です。
(追記:これは勘違いでした。先ほど文面を再確認したところ「And thank you, it now compiles, I moved up the include for the SDFileSystem in front of everything else.」と自己解決した事が書かれていました。但し、なぜこれで解決できたのかは記されていません。興味のある人は下記解説もご覧下さい。)

mbedのFATFileSystemはChaNさんの実装したPetit FAT File System Moduleを起点にしているようです。
integer.hがhttp://mbed.org/projects/libraries/svn/FATFileSystem/trunk/integer.hにあります。

integer.hの27行目は
typedef enum { FALSE = 0, TRUE } BOOL;
となっています。

ごく稀にライブラリでこの手の実装を見かけますが、これはあまり良い実装とは言えません。
なぜなら、他の誰かが同じような定義を異なる手段で提供している可能性もあるからです。
これは通常、良くてコンパイルエラー、悪くて設計と異なる挙動を生みます。

私の場合、他に幾つかのライブラリを組み合わせていました。
怪しそうなライブラリのソースコードをダウンロードして調べます。


そうするとありました。
EthernetNetIfを使っているのですが、LPC1768/lwip/arch/cc.hに定義があります。
#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif
cc.hが先にプリプロセッサに通ってしまうと、integer.hの方は
typedef enum { 0 = 0, 1 } BOOL; 
となってしまいます。当然これではコンパイル不能です。

ライブラリは私の設計実装ではないので仕方ありません。
インクルード順序を変更してみます。
#include "EthernetNetIf.h"
#include "SDFileSystem.h"

#include "SDFileSystem.h"
#include "EthernetNetIf.h"
に変更しました。
今回の場合、これによってコンパイルエラーを回避できます。



Davidさんの場合、SDFileSystem.hをなぜか2回(11行目でも)インクルードしています。
最初の記述ではこの位置でインクルードしていたのでしょう。
彼の自己レスにもあるように、最初の方にインクルードを移動することでコンパイルが通ります。
#include "mbed.h"
#include "SDFileSystem.h"
#include "HTTPServer.h"
#include "HTTPRPC.h"
#include "HTTPFS.h"
#include "HTTPStaticPage.h"
といった感じですね。

ライブラリの実装は他の人も参加することを前提に設計しなくてはと改めて考えさせられる出来事でした。

0 件のコメント:

コメントを投稿