第11回 UNIXによるソフト開発2

C言語は元来,UNIXを書くために考案された言語であった.UNIXに代表されるOSは,コンピュータのハードウェアに密接に関わるプログラムであり,それまで,機械語(アセンブリ言語)でしか書くことが出来なかった.即ち,C言語は,そもそも,機械語(アセンブリ言語)の代わりになるように作られたのである.この様な経緯で,C言語はそれまでのFortranやBasic言語などのように単に数値演算をしたり,グラフィックを描いたり出来るだけではなく,ハードウェアを直接制御する能力に長けていたのである.

この特徴によって,車や航空機,ロボットなどの制御を行うには,現在もC言語を用いることが常識のようになっている.OSは通常,リアルタイムOSと呼ばれる特殊なものが使用されるが,これらもUNIXに似ているものが多く,ソフトウェアの開発環境もUNIX上に構築されることが多い.

ここではそのUNIX上でのプログラム開発の一端を見てみよう.

本講義で身につけた知識が役立つ科目等: コンピュータ機械工学,メカトロニクス実習,ゼミ及び卒業研究,大学院での研究等.

11.1 UNIX上のC言語によるソフト開発

プログラムのソースコード自体は,Windows上でのものとさほど変わりがない.ただし,Windows上のVisual C++やVisual Studio等のような統合環境が用いられることはあまり無く,ターミナルとエディタを駆使して行われるのが通例である.

11.2 プログラム手法の進化

プログラムコードの書き方は日々進化している.30年ほど前,goto文によってプログラム中の何処にでもジャンプできるプログラム手法があまりに分かり難いものであったため,以後,

などのように進化してきている.この進化はおよそ以下のような目的を達成しようという方向に向かっている.

  1. プログラムの構造がわかりやすく,読みやすくする.
  2. プログラムを小さな単機能のまとまりに分解して,バグが入りにくくする.
  3. プログラムの他の部分への依存度を減らし,再利用可能にする.

ここではモジュール化と,それを支援するmakeというプログラムの使用方法について解説しよう.

関数を使わない例

まずは関数を使わない例を示す.このプログラム例は,十分に小さいので,バグが入り込む余地は少ないが,それでもfor文が2つ重なって(ネストされて)おり,それぞれのfor文が,どのような意味を持つのか,わかりにくくなっている.

関数を使ったプログラムの例

上のプログラムの内側のfor文の部分を切り出して関数にした例.このように関数にすると,内側のfor文は,「円(楕円)を一周分描く」という意味であるということを明示的に示すことができる.

このように,単機能に分解し,その機能にわかりやすい名前をつけると,その関数部分が再利用しやすくなったことに留意されたい.

尚,上の例とは楕円の計算の部分の違いは,計算結果がどちらのプログラムから出力されたかがわかるように異なるようにしているだけであり,特に深い意味はない.

11.3 モジュール化とmake

機能を関数に分解したら,今度はそれをファイルに分割(モジュール化)すると,こんどは様々な別のプログラムからも再利用できるようになる.

このようにモジュール化したプログラムの例を以下に示す.

myfunc.cpp

ユーザ定義の関数myfunc()を,myfunc.cppという独立したファイルに作成している.

myprog.cpp

myprog.cppはメイン関数である.

【注意】 18行目に改行をプリントしているのは,後のGNUPLOTの書式にあわせるためである.データの中に,空の行(改行コードだけ)があると,そこで線の描画を一端切ることができる.

myfunc.h

ユーザ定義の関数myfunc()を,外部から使用するためにはヘッダファイルが必要である.ヘッダファイルは以下のように定義する.#ifndef ...などの部分は,同じヘッダファイルが2回以上インクルードされてしまった場合の対策であり*,ヘッダファイルを作成するときには必ずこのようにする,決まり文句である.

*同じ関数名の定義を2回以上行うとコンパイルエラーとなるため,過去に呼び出されたかどうかを調べ,過去に呼び出されていたらスキップしている.

Makefile

このプログラムのコンパイルは,以下のようにすればできる.

$ g++ myprog.cpp myfunc.cpp -o myprog

しかし,デバッグ中は何度もコンパイルすることになるので,このような長いコマンドを毎回打つのは非効率的である(実際のプログラムでは,ファイル数が何十にも及ぶことがある).この様な時,makeを使用すると,

$ make

とするだけでコンパイルすることができる.makeを使用するには,以下のようなMakefileを作成する.

makeは,まずMakefileを上から順番に解析していき,ファイルの依存関係を調べる.

  1. 同じディレクトリ内にmyprogが存在するかどうかを調べる(8行目).
  2. myprogがmyprog.oとmyfunc.oに依存している(から成り立っている)ことが10行目よりわかる.
  3. 次にmyprog.oとmyfunc.oの成り立ちをそれぞれ調べ,myprog.oはmyprog.cppより(13行目),myfun.oはmyfunc.cppとmyfunc.hより成り立っている(16行目)ことがわかる.
  4. ファイルの依存関係が判明したら,ファイルスタンプ(作成日時)を調べ,時間に矛盾があれば(作成元よりも古い,など)そのファイルを作成しなおす.たとえば,myprogがmyprog.oかmyfunc.oのいずれかよりも古ければ(10行目),11行目を実行する.
メイクファイル名をMakefileとすると自動で読み込まれる.別の名前(たとえばmyprog.mak)などとした場合は,make -f myprog.makと明示して読み込ませることができる.

【追加情報6/28】 メイクファイル中の処理実行部分(上記の例で,11,14,17,20行目)の先頭は,スペースではなく,タブである必要があることに注意.

11.4 プログラムの実行

プログラムコードとメイクファイルが正しければ,myprogという実行コードが作成されるはずである.このコードは,

$ ./myprog

とすることで実行できるが,このままでは大量の計算結果を画面に出力してしまう.UNIXでは*本来なら画面に表示される出力先(これを標準出力という)を,任意の出力先に切り替える(リダイレクションredirectionという)ことができる.これは,

$ ./myprog > ファイル名

とすることでできる.ここではファイル名をxy.datなどとして保存しよう.

*実は同じことがWindowsのコマンドプロンプトでも出来る.

11.5 GNUPLOT

では出力したデータを使ってグラフを書いてみよう.UNIX/Linux環境では(もちろんCygwin-X環境でも),Gnuplotという便利なグラフ描画ソフトが利用できる.作成したデータファイルをいちいちExcelなどに取り込んでグラフを書くよりもはるかに便利である.

Gnuplotを起動するには,コマンドラインから,

$ gnuplot

と入力すると,以下のような画面が出力される.

ここで,

gnuplot> splot "xy.dat" with lines

と入力すると,以下のようなグラフがプロットされる.

【ヒント】 マウスを使ってプロット画面をドラッグすると,グラフの表示角度を任意に変えることができる(GNUPLOTのバージョン4以降).
【ヒント】 splotは3次元のグラフを書くコマンドである.
【ヒント】 2次元のグラフを書くコマンドは,plotである.

課題

  1. モジュール化のサンプルプログラムではxyを計算したが,非モジュール化の例では楕円を計算している.この楕円の計算プログラムをモジュール化せよ.このとき,ファイル名はそれぞれ以下のようにせよ.
    circle_YCNN.cpp, circle_YCNN.h, main_YCNN.cpp, circle_YCNN.mak
    また,makeの結果作成される実行コードの名前を
    circle_plot_YCNN
    となるようにせよ.
  2. 課題1のプログラムで描けるグラフは2次元であった.これを改造して,3次元の回転楕円を描くプログラムを作成してみよ.ファイル名は,
    circle3d_YCNN.cpp, circle3d_YCNN.h, main3d_YCNN.cpp, circle3d_YCNN.mak
    などとせよ.
    また,makeの結果作成される実行コードの名前も同様に
    circle3d_plot_YCNN
    となるようにせよ.

上記のファイル群をメールに添付して提出せよ.

【注意】 課題1の楕円のプログラムで描けるグラフは2次元である.
【注意】 実行コードおよび実行結果のデータは提出しないこと.提出するのはソースコードのみ.
【注意】 プログラムを実行して出来るデータファイルで,グラフが描けることを確認せよ.

提出期限は来週月曜午後5時までとする.


Further Readings - C++

最新のデータ隠蔽,カプセル化技術を用いたプログラム例

ファイルは一つなので,g++でそのままコンパイルできる.gnuplotをプログラムから直接呼び出してアニメーションを行っている.

Further Readings - GNU Make

makeについて非常に詳しく書かれている大著.

「GNU Make」,ロバート メクレンバーグ (著), オライリージャパン

Further Readings - GNUPLOT

GNUPLOTは非常に多機能なグラフソフトであり,インターネット上にも多くの情報があるが,ここでは以下の書籍を参考にした.

「使いこなすGNUPLOT」,大竹つよし著,テクノプレス