Archive for the ‘newlisp.dll’ Tag

UTF-8 版 newLISP.dll を Visual C++ で使う(続き)

 newLISP.dll を使った CLR コンソール アプリケーション
 前回は直接起動しましたが、今回は、DOS窓(コンソール)から起動してみました。


 コードページは、932 ですから、日本語コードは Shift-JIS のはず。
 でも、日本語コードが UTF-8 に見えます。
 コードページ 932 の DOS 窓でも UTF-8 は使え、それは、アプリケーション次第ってこと?
 ちにみに、”anni.lsp” は、

(define (get-anniversary-from-wiki day)
  (letn (str (get-url (string "http://ja.wikipedia.org/wiki/"
                              (day 0)
                              "%E6%9C%88"
                              (day 1)
                              "%E6%97%A5"))
         str1 (replace "\n" str ""))
    (when (find "記念日・年中行事</span></h2>(.*)関連項目" str1 0)
      (letn (tmp $1
             pos (find "<h2>" tmp)
             kday (0 pos tmp)
             kparse (xml-parse kday (+ 1 2 4))
             res '())
        (dolist (kp kparse)
          (dolist (k (kp 2))
            (let ((tmp "") (ddpos (ref "dd" k)))
              (dolist (x (ref-all "TEXT" k))
                (when (and ddpos (< ddpos x)) (push "\n    " tmp -1) (setq ddpos nil)) 
                (inc (x -1))
                (push (k x) tmp -1))
              (unless (null? tmp)
                (push tmp res -1)))))
        res))))
(define (jnow)
  (now (- ((now) 9))))
(setq today-ani (get-anniversary-from-wiki (1 2 (jnow))))
(when today-ani
  (dolist (x today-ani)
    (if (starts-with x "\n") (print x) (silent (print (string "\n・" x)))))
  (println))

 こんな感じ。ただし、UTF-8 コードで保存してあります。日本語の Windows では、Shift-JIS が標準ですから、注意して下さい(笑)。
 基本的には、前の blog で紹介した、“newLISPで Wikipedia を参照する...応用編”から、UTF-8 → Shift-JIS変換 を外したものです。
 ちなみに、”anni.lsp” を UTF-8版newLISP で実行すると、


 文字化けします。こちらが当然なのですが、、、
 DOS 窓の不器用さを嘆くべきか? CLR コンソール アプリケーション の器用さを讃えるべきか?

 いずれにせよ、Windows の DOS窓で UTF-8 が使えるのうれしい話です。

 以上、如何でしょうか?

UTF-8 版 newLISP.dll を Visual C++ で使う

 前回は、newLISP.dll をコンソール アプリケーションで使いました。
 Visual C++(私の使っているのは、Express Edition) のコンソール アプリケーションには、Win32 の Win32 コンソール アプリケーション (前回のコンソール アプリケーション)の他に、CLR コンソール アプリケーション があります。
 何が違うかというと、日本語コードが UTF-8 になります。
 Visual C++ の開発環境で、

新規作成 → 新しいプロジェクト → CLR → CLR コンソール アプリケーション

 という風に進めて、新規プロジェクト CLR-newLISP を作成すると、

// CLR-newLISP.cpp : メイン プロジェクト ファイルです。

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    Console::WriteLine(L"Hello World");
    return 0;
}

 といった具合にテンプレートが出てきます。
 CLR コンソール アプリケーション だと、見ての通り、文字列に String が使えます。
 日本語版Visual C++ の String の文字コードは、UTF-8 です。
 つまり、UTF-8版newlisp.dll を使うには、最適(笑)!
 ということで、以下コードです。

// CLR-newLISP.cpp : メイン プロジェクト ファイルです。

#include "stdafx.h"
#include <windows.h>
using namespace System;
using namespace System::Text;
using namespace System::Runtime::InteropServices;

	int String2char(String^ str, char* text)
	{
		Encoding^ utf8 = Encoding::GetEncoding(L"UTF-8");
		array<Byte>^ utf8Array;//
		utf8Array = utf8->GetBytes(str);
		Marshal::Copy(utf8Array, 0, (IntPtr)text, utf8Array->Length);
		text[utf8Array->Length] = '¥0';
		return utf8Array->Length;
	}
	String^ char2String (char* text) {
		int len = strlen(text);
		Encoding^ utf8 = Encoding::GetEncoding(L"UTF-8");
		array<Byte>^ utf8Array = gcnew array<Byte>(len);
		array<Char>^ utf8Chars;
		Marshal::Copy((IntPtr)text, utf8Array, 0, len);
		utf8Chars = utf8->GetChars(utf8Array);
		return gcnew String( utf8Chars);
	}
#define MAXBYTES	512
typedef int (__stdcall *newlispAPI)(IN LPCSTR script);

int main(array<System::String ^> ^args)
{
	String^	readdata;
	static newlispAPI newlispEvalStr = NULL;
	char script[MAXBYTES];
	char* res;
	int len;
	HMODULE hnewLISP = LoadLibrary(TEXT("newlisp.dll"));
	if (hnewLISP) {
	    Console::WriteLine(L"Hello newLISP World");
		newlispEvalStr = (newlispAPI)GetProcAddress(hnewLISP, "newlispEvalStr");
		Console::Write("> ");
		while ((readdata = Console::ReadLine()) != "(exit)") {
			len = String2char(readdata, script);
			res = (char *)newlispEvalStr((LPCSTR) script);
			Console::Write(char2String(res) + "> ");
		}
		Console::WriteLine("Press Enter key!");
		Console::ReadLine();
		if (hnewLISP) FreeLibrary(hnewLISP);
	} else {
		Console::WriteLine("newlisp.dll is not found.");
		Console::WriteLine("Press Enter key!");
		Console::ReadLine();
	}
	return 0;
}

 コードの解説は、、、ここは、newLISP の blog なので、割愛(笑)。
 これをコンパイルして実行すると

 こんな感じ。もちろん、UTF-8版newlisp.dll を用意しておく必要があります。
 newLISP インストール・ディレクトリに PATH が通っているなら、CLR-newLISP.exe と同じディレクトリに置いておく必要があります。
 これなら、Windows 環境の newLISP で普通に UTF-8 が使えます。
 なんせ Windows 環境の コンソール(DOS窓)は、Shift-JIS コードが標準ですから、UTF-8版newlisp.exe では、うまく日本が使えませんでした。chcp とかも試したのですが、、、
 しかし、これからは、Windows でも、UTF-8版newLISP が使える?
 それなら、Linux 用コードと分けなくて済む?(笑)

 以上、如何でしょうか?

newLISP.dll を C で使う

 Windows では、実行ファイル newlisp.exe の他に newlisp.dll があります。
 Unix の newlisp.so には、C 言語からの呼び出し例がマニュアルに載っていますが、newlisp.dll の項目 には、C 言語からの呼び出し例は載っていません。
 そこで、作ってみました(笑)。

 コンパイラが bcc の場合、

/* libdemo.c - demo for importing newlisp.dll
 *
 * use:
 *
 *    libdemo "(+ 3 4)"
 *    libdemo "(symbols)"
 *
 */
#include <stdio.h>
#include <windows.h>

typedef int (__stdcall *newlispAPI)(IN char* script);

int main(int argc, char* argv[])
{
	HMODULE hLibrary;
	newlispAPI func;

	if ((hLibrary = LoadLibrary("newlisp.dll")) == 0) {
	    printf("cannot import library\n");
		exit(-1);
	}

	func = (newlispAPI)GetProcAddress(hLibrary, "newlispEvalStr");

 	if (argc > 1) {
		printf("%s\n", argv[1]);
		printf("%s\n", func(argv[1]));
	}

	return(0);
}

 マニュアルにある Unix 版とほぼ同じ動作ですが、コマンドライン引数も出力するようにしてあります。
 また、引数は、"(ダブル・クォート)で囲みます。

 ついでに、Visual C++ の場合、こうなります。

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>

typedef int (__stdcall *newlispAPI)(IN LPCSTR script);

int main(int argc, char* argv[])
{
	HMODULE hLibrary;
	newlispAPI func;

	if ((hLibrary = LoadLibrary(L"newlisp.dll")) == 0) {
	    printf("cannot import library\n");
		exit(-1);
	}

	func = (newlispAPI)GetProcAddress(hLibrary, "newlispEvalStr");

 	if (argc > 1) {
		printf("%s\n", argv[1]);
		printf("%s\n", func((LPCSTR) argv[1]));
	}

	return(0);
}

 キャストが微妙に違っています(笑)が、基本動作は同じです。

 さて、newlisp.dll の組込シンボルを symbols 使って見てみると、

Class
Tree
module

 の三つがありません。いずれも、予約変数または関数で、newlisp.exe にはあります。
定義がマニュアルにありますので、困ることはないでしょうが、ご使用の際は、ご注意を。

 以上、如何でしょうか?