» 詳しい使用方法や、エラーで展開できない際の対応方法などはこちら
C言語のプログラムをGUIで包む(2: 入力値をコマンド引数で渡す編)
VCSSLから、C言語製のプログラムを呼び出し、その出力内容を画面に表示します。
今回は 前回 の発展として、ユーザーからの入力値を、C言語プログラム起動時のコマンド引数として渡すようになっています。
使用方法
ダウンロードと展開(解凍)
まず、PC(スマホは未対応)で上の画面の「 ダウンロード 」ボタンを押してください。 するとZIP形式で圧縮されたファイルがダウンロードされます。
その後、ZIPファイルを右クリックして「すべて展開」や「ここに展開」などで展開(解凍)してください。 展開が成功すると、ZIPファイルと同じ名前のフォルダができ、その中にZIPファイルの中身が入っています。
» 展開がエラーで止まってしまう場合や、ファイル名が文字化けしてしまう場合は…
プログラムの起動
Windows をご使用の場合
上記でZIPファイルを展開したフォルダ内にある、以下のバッチファイルをダブルクリック実行してください:
もしプログラムを書き変えながら使いたい場合は、代わりに「 VCSSL_Editor__プログラム編集はこちら.bat 」を実行してください。
正常に起動できると、初回のみ、Java実行環境を入手するか等を尋ねられるので、適時答えて済ませると、プログラムが起動します。 2回目以降はすぐに起動します。
Linux 等をご使用の場合
ZIPファイルを展開したフォルダ内へコマンドライン端末で cd して、以下の通り入力して実行してください:
(プログラムの内容を書き変えながら使いたい場合は、代わりに VCSSL_Editor.jar を実行)
» javaコマンドが使用できない等のエラーが表示される場合は…
起動後
このVCSSLプログラムを実行すると、まず入力ウィンドウが3回立ち上がり、値A,B,Cの入力を求められます:
続いて、以下のようなセキュリティ警告が表示されるので、「はい」を押して続行します。
※ 今回扱う「外部プログラムの実行」処理は、VCSSLのセキュリティの監視範囲の外側で動作するため、何でも行えてしまいます。それを認めますか?という意味です。 信頼できないプログラムでは安易に「はい」は押さないようにしましょう。
なお、毎回このメッセージが出るのがうっとうしい場合は、VCSSLの画面の上から「セキュリティ」>「システムコマンドの実行を許可」にチェックを入れると出なくなります。
すると、C言語製のプログラム program.exe が実行され、先ほど入力した値A,B,Cが、起動時の引数として渡されます。
このサンプルでのC言語プログラムは、起動時の引数 argv の内容を出力するようになっています。 その出力内容は、VCSSLコンソール(黒い画面)上に、以下のように表示されます:
引数[0]の内容: C:\(...略...)\program.exe
引数[1]の内容: aaa
引数[2]の内容: bbbb
引数[3]の内容: ccccc
引数[1]が値A, [2]がB, [3]がCの内容です。
最初に入力した値が、きちんとC言語プログラムに渡されている事を確認できますね。
なお、ここで実行されている「program.exe」は、Windows 用にコンパイルされた実行ファイルであるため、Linux 等の他種OSでは動作しません。 他のOSで実行したい場合は、C言語のソースコード「program.c」をコンパイルし直して、VCSSLからの呼び出し箇所も調整してください(拡張子が .exe ではなく .out 等になるはずです)。
題材解説
この連載について
VCSSLのような簡易的なスクリプト言語のプログラムから、C言語のような「別の言語」で書いたプログラムを呼び出したい、といった場面はよくあります。
今回の記事は、そのテーマでの連載の第2回です。
前回の発展として、起動時の引数でパラメータを渡してみる
初回である 前回 は、
- 単純な Hello World のC言語プログラムを、VCSSLから呼んで起動して、出力を受け取って表示してみる
という内容を扱いました。
今回はそれを少しだけ発展させて、
- C言語プログラムに、起動時の引数として、処理に使うパラメータを渡してみる
というサンプルコードになっています。
GUIはまだ単純版、次回でアプリ的な画面を作る
GUIについては、今回はまだ先述の通り、「ポップアップウィンドウを連続表示して、値を入力してもらう」という形態です。
これは、使う際はやや面倒くさいですが、VCSSLでの実装コードが非常に単純で済むという利点があります。実際、今回のコードは、前回のコードに少し追記するだけで済みます。
次回 は、ちょっとしたアプリのような画面を作ってみます。そちらはコードも少し複雑になります。
コード解説
メインのプログラムは、VCSSLで書かれています。VCSSLはC言語系のシンプルな文法を採用しているので、C言語ユーザーの方なら普通に読み書きできると思います。
コード全体
まずVCSSLのコードを見てみましょう。以下がコード内容の全体です:
- GUIWrapperInputArgs.vcssl -
coding UTF-8;
// 必要なライブラリの読み込み
import File;
import Process;
// 実行するC言語プログラムファイルの絶対パスを取得
string programPath = getFilePath("program.exe");
// C言語プログラムを起動する際の、コマンド内容を格納する配列を用意
string commandWords[4];
// 最初の要素は、実行するプログラムのパスを詰める
commandWords[0] = programPath;
// それ以降の要素は、プログラムに渡すパラメータであるため、ユーザーに入力してもらう
commandWords[1] = input("値Aを入力してください:", "aaa");
commandWords[2] = input("値Bを入力してください:", "bbbb");
commandWords[3] = input("値Cを入力してください:", "ccccc");
// プログラムを実行可能な状態に用意する(ここで上記で用意したコマンド内容を渡す)
int processID = newProcess(commandWords);
// 日本語の文字化けを防ぐため、文字コードを指定
// (逆に文字化けしてしまう場合は、"UTF-8" などを指定する)
setProcessInputEncoding(processID, "CP932");
setProcessOutputEncoding(processID, "CP932");
setProcessErrorEncoding(processID, "CP932");
// プログラムを実行し、終了を待機する
startProcess(processID);
waitForProcess(processID);
// プログラムの出力内容を取得し、VCSSLコンソール(黒い画面)に表示
string output = getProcessOutput(processID);
println(output);coding UTF-8;
// 必要なライブラリの読み込み
import File;
import Process;
// 実行するC言語プログラムファイルの絶対パスを取得
string programPath = getFilePath("program.exe");
// C言語プログラムを起動する際の、コマンド内容を格納する配列を用意
string commandWords[4];
// 最初の要素は、実行するプログラムのパスを詰める
commandWords[0] = programPath;
// それ以降の要素は、プログラムに渡すパラメータであるため、ユーザーに入力してもらう
commandWords[1] = input("値Aを入力してください:", "aaa");
commandWords[2] = input("値Bを入力してください:", "bbbb");
commandWords[3] = input("値Cを入力してください:", "ccccc");
// プログラムを実行可能な状態に用意する(ここで上記で用意したコマンド内容を渡す)
int processID = newProcess(commandWords);
// 日本語の文字化けを防ぐため、文字コードを指定
// (逆に文字化けしてしまう場合は、"UTF-8" などを指定する)
setProcessInputEncoding(processID, "CP932");
setProcessOutputEncoding(processID, "CP932");
setProcessErrorEncoding(processID, "CP932");
// プログラムを実行し、終了を待機する
startProcess(processID);
waitForProcess(processID);
// プログラムの出力内容を取得し、VCSSLコンソール(黒い画面)に表示
string output = getProcessOutput(processID);
println(output);
GUIWrapperInputArgs.vcssl
このコードは、内部でC言語製のプログラム「program.exe」(Windows用にコンパイル済み)を呼び出しています。こちらのソースコードは以下の通りです:
- program.c -
#include
// 以下の引数 argv に、VCSSL側からの入力値が渡される
// ※ argv[0] にはプログラムの名前やパスが格納されているが、それはC言語側の仕様
int main(int argc, char *argv[]) {
printf("-- C言語プログラムからの出力内容 --\n");
// 引数 argv の内容を、全て標準出力に表示する
for (size_t iarg=0; iarg<argc; iarg++) {
printf("argv[%zu]の内容: %s\n", iarg, argv[iarg]);
}
}
program.c
上記の通り、起動時に渡された引数 argv の全要素を、標準出力に説明付きで流す内容になっています。出力内容の例は以下の通りです:
argv[0]の内容: C:\(...略...)\program.exe
argv[1]の内容: aaa
argv[2]の内容: bbbb
argv[3]の内容: ccccc
それでは、以降ではVCSSLコードの細部をピックアップして、先頭から順番に見ていきましょう。
ライブラリのインポート
まずは先頭で、このコードが文字コード「UTF-8」で書かれている事を宣言し(誤読対策)、続いて必要なライブラリを読み込んでいます:
coding UTF-8;
// 必要なライブラリの読み込み
import File;
import Process;
import.txt
File は、ファイルパスの取得や変換などを行うライブラリです。今回は実行対象プログラムの絶対パスを取得するのに使用しています。
Process は、外部プログラムの実行や制御を行うためのライブラリです。
実行対象プログラムの絶対パスを求める
次です。ここでは、実行対象の外部プログラムの実行ファイル(今回の場合は program.exe)の絶対パスを求めています:
// 実行するプログラムファイルの絶対パスを取得
string programPath = getFilePath("program.exe");
getpath.txt
これは、プログラムを曖昧な形で指定すると(プログラム名だけなど)、環境によって探す場所の基準や優先度などが異なり、動いたり動かなかったりするトラブルが生じる可能性があるためです。
なので、初手で絶対パスにしておいた方が安定します。
外部プログラムを実行するコマンドを用意
続いて、外部プログラム(program.exe)を実行するためのコマンド内容を用意します。
ここでコマンド内容というのは、例えばコンパイルしたC言語プログラム(program.exe)を実行する際、従来はコマンドライン端末から
みたいに入力したりしますよね? あれです。あのコマンド内容を、VCSSLのコード内で用意して、実行をリクエストするわけです。
コマンド内容は、VCSSLのコード内では、文字列型の配列として用意します:
// C言語プログラムを起動する際の、コマンド内容を格納する配列を用意
string commandWords[4];
alloc_commands.txt
そして先頭要素には、実行するプログラム(program.exe)を指定するのですが、先ほどのステップで取得しておいた絶対パスを詰めます(環境による解釈ブレ防ぐため):
// それ以降の要素は、プログラムに渡すパラメータであるため、ユーザーに入力してもらう
commandWords[1] = input("値Aを入力してください:", "aaa");
commandWords[2] = input("値Bを入力してください:", "bbbb");
commandWords[3] = input("値Cを入力してください:", "ccccc");
command0.txt
で、続く [1] 以降には、プログラムに渡すパラメータを詰めます。今回は、ユーザーに尋ねて、値を入力してもらうようにします:
// 最初の要素は、実行するプログラムの絶対パスを詰める
commandWords[0] = programPath;
command123.txt
実行可能な状態に用意
続いて、上記で用意したコマンド内容から、プログラムを実行可能な状態(プロセス)として用意します。これには newProcess 関数を用います。
// プログラムを実行可能な状態に用意する(ここで上記で用意したコマンド内容を渡す)
int processID = newProcess(commandWords);
newprocess.txt
newProcess 関数の引数には、実行対象の外部プログラムのファイルパスを渡すのですが、その際、絶対パスを取得して渡す事が推奨されます。相対パスやファイル名だけだと、実行環境や実行方法によっては失敗する事があるためです。
よってここでは、getFilePath 関数で「program.exe」の絶対パスを取得して、それを newProcess 関数に渡しています。
newProcess 関数は、戻り値として「プロセスID」を返しますが、それを変数 processID に控えています。このプロセスIDは、外部プログラムを実行・制御する際に、引数として指定する必要があります。
文字コード設定
今回のように、外部プログラムの入出力内容が日本語を含んでいる場合には、よく文字化けが問題になります。
そこで、外部プログラムとの入出力に使う文字コードを、実行前に指定します:
// 日本語の文字化けを防ぐため、文字コードを指定
// (逆に文字化けしてしまう場合は、"UTF-8" などを指定する)
// setProcessInputEncoding(processID, "CP932");
// setProcessOutputEncoding(processID, "CP932");
// setProcessErrorEncoding(processID, "CP932");
setencoding.txt
外部プログラムが何かを出力する際、それがどの文字コードを用いるかは、そのプログラムやコンパイラによって異なります。
日本語のメッセージを出力するC言語製のプログラムは、Windows 環境でコンパイルすると、文字コード「CP932(≒Shift_JIS)」を用いる事が結構多い状況です。そのため、上では CP932 を指定しています。
逆にそれによって文字化けしてしまう場合は、UTF-8 などを試してみてください。
実行開始と終了待機
続いて、startProcess 関数で外部プログラムを実行し、waitForProcess 関数で終了を待機します。
// プログラムを実行し、終了を待機する
startProcess(processID);
waitForProcess(processID);
start.txt
終了を待機せずに、双方向に入出力を繰り返しながら、処理を進めていく事も可能です。
しかし今回のように「外部プログラムが一方的に内容を出力して終わり」という場合は、実行開始と同時に終了を待機してしまった方が手短です。出力内容は後でまとめて拾えます。
出力内容を取得して、VCSSL側の画面に表示
さて、最後です。外部プログラムが実行中に出力した内容をまとめて取得し、それをVCSSLコンソール(黒い画面)に表示します:
// プログラムの出力内容を取得し、VCSSLコンソール(黒い画面)に表示
string output = getProcessOutput(processID);
println(output);
output.txt
このように、 getProcessOutput 関数で、外部プログラムが今までに出力した内容を取得できます。
他にも、 onProcessOutput イベントハンドラを定義して、行単位でリアルタイムに拾う方法もあります:
void onProcessOutout(int processID, string output) {
print(output);
}
event.txt
どちらの方法が扱いやすいかは、出力をどう捌きたいかによります。
今回のコード内容は以上です。
どうだったでしょうか? まだ「GUIで包んだ」と呼べるレベルではないものの、VCSSLからC言語のプログラムを呼び出して、入出力を行う感覚は掴めたでしょうか。
次回 は、いよいよ、ちょっとしたアプリ風のGUI入力画面を作ってみます!
ライセンス
このVCSSL/Vnanoコード( 拡張子が「.vcssl」や「.vnano」のファイル )は実質的な著作権フリー(パブリックドメイン) である CC0 の状態で公開しています※。 記事中にC言語/C++/Java言語などでのサンプルコードが掲載されいてる場合は、それらについても同様です。 そのままでのご利用はもちろん、改造や流用などもご自由に行ってください。
※ ただし、このコードの配布フォルダ内には、ダウンロード後すぐに実行できるように、 VCSSLの実行環境も同梱されており、そのライセンス文書は「 License 」フォルダ内に同梱されています (要約すると、商用・非商用問わず自由に使用できますが、使用の結果に対して開発元は一切の責任を負いません、といった具合の内容です)。 配布フォルダ内の各構成物の一覧やライセンスについては「 ReadMe_使用方法_必ずお読みください.txt 」をご参照ください。
※ Vnano の実行環境については、別途スクリプトエンジンのソースコードも一般公開しており、 何らかのソフトウェア内に組み込んでご利用いただく事も可能です。詳細はこちらをご参照ください。












