Archive for the ‘C’ Tag
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 にはあります。
定義がマニュアルにありますので、困ることはないでしょうが、ご使用の際は、ご注意を。
以上、如何でしょうか?