basicインタプリタをマクロ言語として使用する



■basicインタプリタを VB.net / C# で作成したWindowsアプリケーションに組み込んで
マクロとして使用する方法を考えてみたいと思います

なぜ VB.net / C# であるかというと、DLLを作成した時の文字列の受け渡しが簡単に出来るからです
VB6を使うと、文字列変換部分だけでかなり大掛かりになり、本来の目的からそれてしまいます



■マクロとは、
エクセルで言うVBAの事を指します。
VBAによりエクセルは非常に柔軟性のあるプログラムになっていますよね
そんな機能を自分のプログラムに組み込む実験をしてみたいと思います
いくらなんでも自作インタプリタはVBAほどパワフルではないですけど・・・・



■基本的なマクロの動作について考える


まず、アプリケーション側から変数にアクセスできることが必須です
変数を設定してインタプリタを起動させ、インタプリタが実行を終了した時点で
アプリケーションが変数の値を読み出して使用するという形にしたいと思います

インタプリタの初期化をシンプルにするために
インタプリタのマクロは作成するDLLと同一ディレクトリの main.txt に
決め打ちしたいと思います
DLLの起動時に自動的に main.txt が読み込まれるようにします



▼上記の要求を満たす公開関数を考えました


//変数の値を取得する
char* WINAPI getVari(char*name)

//変数に値を設定する
void WINAPI setVari(char*name,char*val)

//インタプリタの実行開始
void WINAPI start()

この3つの公開関数のみでとりあえずマクロとして動作するはずです



■自作basicインタプリタのDLL化


インタプリタの開始部分は本来の開始部分の関数名を  void WINAPI start()  に変更しました
変数の値の 設定/取得 はmapの値を返すだけですので次のようなメソッドを追加しました

//変数に値を設定する    nameが変数名  valが値
void WINAPI setVari(char*name,char*val){
	//文字列であるか、数値であるか、バリアント変数に判断させる
	VARIANT_ pos;
	char str_pos[MAX_STR_LEN];
	pos=val;
	str_print_(pos,str_pos);
	variable_table[name]=str_pos;
}

//変数の値を取得する    nameが変数名  戻り値が取得した値
char* WINAPI getVari(char*name){
	static char buf[MAX_STR_LEN];
	strcpy(buf,variable_table[name].c_str());
	return buf;
}


次にプロジェクトにdefファイルを追加して、公開するメソッドを書き込みました

EXPORTS
	start
	setVari
	getVari


以上でWin32 DLL としてコンパイルして macro.dll を作成しました



■VisualBasic.netからインタプリタを使用する


▼準備
VB.netで適当にWindowsアプリケーションを作成して
実行ファイルが作成されるディレクトリに上記で作成した macro.dll をコピーします
次にインタプリタで使用されるマクロの main.txt を同一ディレクトリに作成しました

basic.txtの内容

val a	'変数の内容を文字から数字に変換
val b
if mode=="add" then c=a+b
if mode=="sub" then c=a-b

end

変数modeの内容により、処理が足し算もしくは引き算に分岐し、aとbに代入された
値を計算して変数cに代入します



▼VB.netでのプログラムの作成


クラスの中に作成したDLLのAPI宣言を追加し、二つのボタンと3つのテキストボックスを貼り付け
textbox1の値を変数 a に代入し、textbox2の値を変数 b に代入し
計算結果の変数 c の値をtextbox3に代入するようなプログラムを作成しました

押されるボタンにより、変数 mode に値を代入し、
自作インタプリタは、変数 mode の値により処理を分岐させます




Public Class Form1
    Inherits System.Windows.Forms.Form

    'API宣言
    <System.Runtime.InteropServices.DllImport("macro.dll")> _
    Private Shared Sub setVari(ByVal name As String, ByVal data As String)
    End Sub

    <System.Runtime.InteropServices.DllImport("macro.dll")> _
    Private Shared Function getVari(ByVal name As String) As String
    End Function

    <System.Runtime.InteropServices.DllImport("macro.dll")> _
    Private Shared Sub start()
    End Sub

・・・・・・・・・・・・・・・・・・・・・・

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        TextBox1.Text = 6
        TextBox2.Text = 2
        Button1.Text = "add"
        Button2.Text = "sub"
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        setVari("a", TextBox1.Text)
        setVari("b", TextBox2.Text)
        setVari("mode", "add")
        start()
        TextBox3.Text = getVari("c")
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        setVari("a", TextBox1.Text)
        setVari("b", TextBox2.Text)
        setVari("mode", "sub")
        start()
        TextBox3.Text = getVari("c")
    End Sub
End Class



ボタンを押す事にマクロが呼び出され、足し算、引き算が切り替わる事が確認できました
応用していくと凄く柔軟性のあるプログラムが作成できそうです。



■C#の場合のプログラム

API宣言を以下のように設定します

[System.Runtime.InteropServices.DllImport("macro.dll")]
private extern static  void start();
[System.Runtime.InteropServices.DllImport("macro.dll")]
private extern static  string getVari(string name);
[System.Runtime.InteropServices.DllImport("macro.dll")]
private extern static  void setVari(string name,string val);

以下のようにメソッドを呼び出します

setVari("a",textBox1.Text );
start();
string str=getVari("c");

ほとんどVB.netと同じですね



■今回作成したプログラム
basicmacro.ZIP


最新のDLLのソース
ちなみにソースはC++でbasicインタプリタを作るの内容です。

abasic sourceforge.jp




20061004 作成
20141014 DLL(ver 0_1)への差し替えとそれに伴う更新


▲トップページ > プログラミングの実験