VCSSLの最新版をリリース: 外部プログラムとの連携機能を少し強化、他

RINEARN では先日、VCSSLの最新版 Ver.3.4.52 をリリースしました。以下のページからダウンロードできます:

前回のリリースはJava24環境への互換対応を目的としたものでしたが、今回のリリースは機能拡張がメインです。

以下、詳細をお知らせします!

- 目次 -

外部プログラムとの連携機能周りを少し強化

まずは今回のメインとなる「外部プログラムとの連携機能」そのものについて、少し解説しておきましょう。

VCSSLは、他のプログラミング言語で開発された実行ファイル(.exe や .out など)を実行し、標準入出力などを介して連携するための機能があります。

この機能については、VCSSLの公式ドキュメント内の、以下のページで詳しく解説しているため、気になる方はぜひご参照ください:

これをうまく使うと、例えば「自作の単純なC言語プログラムに、VCSSLでパラメータ入力画面とかを作ってかぶせて、ちょっとしたGUIツールにしたい」といった用途をカバーできます。

ただし、あくまでも標準入出力を介した原始的な連携方式のみのサポートなので、複雑で密な連携を要するガチなGUIアプリケーションを組むのは無理があります。そういう場合はDLLとかにして、他のガチなGUI開発をできる言語から呼んだ方がいいです。

文字化け対策の機能を追加

それでは本題に入っていきます。今回は、外部プログラムとの連携を少し強化するための拡張をいくつか加えました。その一つが「文字化け対策」です。

標準入出力内容の「文字化け」がしばしば問題になる

複数のプログラム間で文字列の情報をやり取りする際には、しばしば「文字化け」が問題になります。 これは、プログラムAが何かを出力する際の文字コードと、それをプログラムBが受け取る際の文字コードが食い違う際に生じます。

で、少し前までは、Windows上で日本語を扱うプログラムは、「CP932」という文字コードを標準で使う事が多かったです。 しかし数年前からあちこちで「UTF-8」に移行する流れが加速してきて、あちこちでCP932とUTF-8が混在した少しややこしい状況になっています。

従来、VCSSLと外部プログラムで連携時に文字化けが生じた際に、必要だった対処

さて、現在のVCSSLで外部プログラムを実行した場合、その標準入出力の内容は、文字コード「UTF-8」を用いていると見なして扱われます(デフォルト設定の場合)。

従って、実行したい外部プログラム(C言語等で書いたプログラム)がCP932等の文字コードで標準入出力を行う場合、従来は以下の対処が必要で、それぞれ面倒な点がありました:

今回から、スクリプト内で、実行する外部プログラムの入出力文字コードを指定可能に

そこで今回、外部プログラムの実行に用いる Process ライブラリを少し拡張し、以下の関数を追加しました:

setProcessInputEncoding( int processID, string inputEncoding )
外部プログラムに渡す標準入力の文字コードを設定します。
setProcessOutputEncoding( int processID, string outputEncoding )
外部プログラムから受け取る標準出力を文字コードを設定します。
setProcessErrorEncoding( int processID, string errorEncoding )
外部プログラムから受け取る標準エラーの文字コードを設定します。

これらを用いて、外部プログラムに併せた文字コードを設定してから実行する事で、スクリプト内で手軽に文字化けに対処できるようになりました。

サンプルコード(ダウンロード可)

以下がサンプルコードです:


import File;
import Process;

// ----------------------------------------------------------------------
// example.exe を実行し、標準出力内容を受け取って表示するVCSSLプログラム
// ----------------------------------------------------------------------

// example.exe のプロセスを生成
//("argA/B/C"はプログラムに渡す引数)
string programPath = getFilePath("example.exe");
string processArgs[] = { programPath, "argA", "argB", "argC" };
int processID = newProcess(processArgs);

// example.exe と標準入出力でやり取りする際の文字コードを設定
setProcessInputEncoding(processID, "CP932"); // または "UTF-8" など
setProcessOutputEncoding(processID, "CP932");
setProcessErrorEncoding(processID, "CP932");

// example.exe の処理を実行開始
startProcess(processID);


// 標準出力内容が流れてくるイベントハンドラ
void onProcessOutput(int sourceProcessId, string text) {
    print(text); // そのまま画面に表示
}

// 標準エラー内容が流れてくるイベントハンドラ
void onProcessError(int sourceProcessId, string text) {
    print(text); // そのまま画面に表示
}
code/ExampleExecution_SJIS.vcssl

上で実行している「example.exe」は、例えば以下のC言語プログラムをコンパイルしたものだったとしましょう:


# include 

int main(int argc, char *argv[]) {
    printf("おはよう!元気?\n");
    return 0;
}
code/example_SJIS.c

これは日本語の

おはよう!元気?

というメッセージを標準出力に吐くプログラムです。VCSSLのコードも、「example.exe」から受け取った上の内容をそのままコンソールに表示する内容になっています。

以下が実行結果です:

で、上のメッセージは日本語なので、ASCIIコードでは表せないマルチバイト文字です。そういう文字は、文字コードがきちんと噛み合っていないと文字化けします(※)。以下が、文字コード指定を "UTF-8" に切り替えた結果です:

文字化けしていますね。

※ 逆に、ASCIIコードの範囲内で表せる "Hello, World!" などの文字列は、文字化けがあまり表面化しません。なぜなら、CP932やUTF-8をはじめ、現在主流の多くの文字コードが、どれもASCIIコードの文字列は正しく読み書きできるように作られているからです(= ASCII互換な拡張になっている)。

ところで、実際にコンパイルした「 example.exe 」とVCSSLコードを、以下にアップしておきました:

よければダウンロードして、試しに setProcessOutputEncoding() 関数で指定している文字コードを "CP932" / "UTF-8" で切り替えて、文字化けしたり直ったりを確かめてみてください。

OSの種類を判定可能に

さて、次です。これも「外部プログラムとの連携強化」の一貫で、今回からOSの種類を簡単に判定可能になりました。

外部プログラムの実行を伴うスクリプトで、複数のOS上で動作させたい場合は、OSによる処理の分岐が必要

上で見てきた例では、C言語のプログラムをコンパイルして「example.exe」を作成し、それをVCSSLのコードから呼んで実行しました。

が、拡張子「.exe」の実行ファイルは、ふつう、 Microsoft Windows® 上でしか実行できません(一応、特殊な環境とかを入れれば他の環境上でも動かせたりしますが)。

とすると、例えば「 C言語+VCSSL で作ったツールを、Windows 上だけでなく Linux 上でも動かしたい 」といった場合には、.exe 形式の実行ファイルの代わりに、Linux 用にコンパイルした .out 形式の実行ファイルなどを実行する必要があります。

これはまぁ、Windows 用と Linux 用に管理/配布パッケージを分けてしまえば済む話ではあります。 しかしメンテやバージョン管理の都合などを考えると、同じ配布パッケージ内に Windows 用と Linux 用の両方の実行ファイルを詰めておいて、実行時に自動で分岐して呼べた方が楽ですよね。

OSの種類を判定するための定数値「OS」が利用可能に

で、そのような利用シーンのために、今回から System ライブラリ(import不要で使用可能)に定数「OS」と「OSVER」を追加しました:

OS
OSの種類を大まかに区別するための文字列値です。
OSVER
OSの開発バージョン/カーネル世代などを大まかに区別するための文字列値です。
※ ここでちょっとややこしいのが、例えば Windows 11 だと、「Windows 11」がOS名で、「11」はバージョンコードではないという事です。 Windows 11 のバージョンコードは、Windows NT の系譜としての「10.0.***」(大まかなカーネル世代のようなもの)や、最近の一般層向け呼称に使われる「25H2」など、色々な方式のものがあります。上記のOSVERの値は、Windows 11上でもWindows10上でも「10.0」となります。

サンプルコード

実際にサンプルコードは以下の通りです:

println(OS);

これをWindows 11 上で実行すると:

Windows 11

一方で Ubuntu 24.04LTS (主要 Linux ディストリビューションの一つ) 上では:

Linux

という情報が表示されます。細かく環境を区別するには情報不足ですが、とりあえず Windows か Linux かは分かるので、たとえば「Windows と Linux の両方で動くツール」みたいなのを作る際にちょっと役立つかもしれません。

「Windows は Windows10か11、Linux は Ubuntu の24LTS以降対応」みたいな細かい条件は、配布時のドキュメントで指定してくださいという方針です。

その他、テキスト処理の機能追加や互換性対策、バグ修正など

その他、今回はいくつか細かいアップデートも入っています。順々に短くまとめます。

文字列内のアルファベットの大文字/小文字揃えなどが可能に

まず、Text ライブラリに以下の関数を追加しました:

これは、文字列値に細かい調整を入れたい場合のためのユーティリティ関数で、引数 mode に応じて以下の操作が可能です:

UPPER_CASE
文字列内のアルファベットを大文字に揃えます。
LOWER_CASE
文字列内のアルファベットを小文字に揃えます。
TRIM
文字列の前後の空白・改行を除去して詰めます。

Java24 環境上での ネットワークドライブ絡みの非互換挙動の対応(の続き)

前回のアップデートで、「Java24環境上で、ネットワークドライブ上のパスが、UNC形式のパスに解決される」という挙動の対策を実施しました。詳細は下記記事参照です:

その後、上記で対処しきれていない挙動が新たに見つかり、今回対処しました。具体的には、

という挙動なのですが、これはVCSSLでは choose(string directoryPath) 関数を使用した際に生じ得ます。今回、それが生じないように対処しました。

※ 一応、この挙動自体は OpenJDKコミュニティに報告済みで、Issue 番号 JDK-8355342 として受理されているのですが、修正時期はまだ未定で、Java側での修正にはしばらく時間がかかりそうです。

「制御文のカッコ内の式内にある文字列リテラルの中に含まれているエスケープシーケンス」の認識不備で変なエラーが出るのを修正

これは上の見出しの通りなのですが、構文解析処理のコーナーケースを突いたエラーで、正しいコードがエラー扱いとなって走らないパターンが見つかったのを直しました。すみません…

-

今回のアップデート内容は、以上の通りです!

今後もVCSSL関連のアップデートは、随時このコーナーでお知らせしていきます。お楽しみに!