FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Linux で Mruby2C-File のビルド / import_C でエラーが出る場合の対処方法

以前の記事「Mruby2CBridgePlugin の使用例 (2)」で、以下のように書いていました。

> ここでは、ビルドおよび実行環境として Cygwin か Linux を想定しています。
> また GNU の make と gcc を使用することにします。
> POSIX 環境であれば、他の環境でも Ruby を使えれば、ビルドできるはずです。

ところが Mruby2C-File を Fedora (3.6.11) 上でビルドしてみるとエラーになってしまいました orz
# MrubyBridgePlugin に関するものは、以前から試していたのですが、Mruby2CBridgePlugin はに関するものは、記事を書く前に Linux は試してなかったのでした

Mruby2C-File/test.cdl の以下でヘッダの取り込みに失敗していました。


import_C( "my_headers.h" );



C のヘッダの取り込み (import_C) は、問題を起こしやすい箇所です。
TECS ジェネレータ tecsgen の import_C が、標準の C の文法に対して不完全であることもありますが、GNU の拡張への対応は、さらに十分ではありません。
ですので、ヘッダファイルを import_C で取り込むときにはエラーが発生しやすくなります。

こういう時は仕方がありませんので、エラーを回避するようにヘッダを少し変更します。
まずは、変更前のヘッダをお見せします(コメントを消去してあります)。

【変更前の my_headers.h】

/* test.cdl import_C this header. */

#include
#include
#include
#include

#ifdef TECS

/* For the TECS generator 'tecsgen' */
typedef intptr_t FILEptr;

#else

/* For the C-compiler */
typedef FILE *FILEptr;

#endif


まず my_headers.h が、何かを説明します。
my_heders.h では stdio.h, sys/types.h, sys/stat.h, fcntl.h を include しています。
実は、これらを個別に import_C すると、TECS ジェネレターはそれらから include されるヘッダを多重に取り込んでしまいます。
import_C は typedef, struct の定義以外取り込みません。
マクロも例外ではありません。
後続の import_C では、二重インクルードを防止するガードコードが有効に働きません。
このために import_C したいヘッダをまとめた my_headersh.h を作成しています。

さらに少し脱線することになりますが、このヘッダには、以前の記事の低水準のファイル I/O だけでなく、高水準のファイル I/O にも対応するようになっています。
FILEPtr 型がマクロ "TECS" の定義の有無により切り替わるようになっています。
マクロ "TECS" が定義されている時は、TECS ジェネレータが import_C で取り込んでいる場合で intptr_t に typedef されます。
一方 "TECS" が定義されていない時は、C コンパイラにより include されている場合で FILE * に typedef されます。
もし、この変更を行わないと MrubyBridgePlugin は、高水準のファイル I/O をインタフェースする関数を生成する際に、FILE 構造体の中身を扱おうとしてしまいます。
しかし、FILE 構造体の中身はシステムが用意してくれているもので、利用者としてはポインタ値(アドレス)以外に関心がありません(持ってはいけません)。
ポインタ値のみを扱いたい場合には intptr_t 型であると tecsgen に申告する必要があります。
(tecsgen 自体は void * でもよいのですが、MrubyBridgePlugin は void * を扱えません)
このために TECS ジェネレータを騙してあげる必要があったのです。
今のところ、これは必要なウソです。


さて、話を元へ戻して、変更後の my_header.h を見てみましょう。

【変更後 my_headers.h】

/* test.cdl import_C this header. */

#ifdef TECS

/* For the TECS generator 'tecsgen' */
typedef intptr_t FILEptr;
typedef long size_t;
typedef int mode_t;

#else

/* For the C-compiler */
#include
#include
#include
#include

typedef FILE *FILEptr;

#endif



マクロ "TECS" が定義されているときは、FILEptr, size_t, mode_t だけが typedef されています。
つまり TECS ジェネレータには CDL ファイル内で参照されている、これらの型が何であるかを教えてあげるだけの、最小限の記述になっています。
C コンパイラには、C 言語標準のヘッダを読み込んでもらうようにします。
TECS ジェネレータが CDL を取り込むときに必要な情報が、前述の typedef だけで、元々ヘッダファイル全体を取り込む必要はなかったわけです。

ヘッダファイルを取り込むときにエラーが出てしまうときは、このように回避するのも一つの方法です。
もし、ご自身でヘッダファイルを書いているのであれば、ヘッダファイル内にマクロ "TECS" の定義の有無により取り込む内容を調整するようにした方がよいです。
あるいは、ラッパー関数を設けるのが、もっとよいかもしれません。
このように TECS ジェネレータを騙すようなやり方をしなくても、すみます。
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

hiro22022

Author:hiro22022
TECS 開発ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。