C#에서 사용 가능한 Tcl 인터프리터입니다.
Wrapping 코드가 포함되어 있으므로 수정해서 사용하시면 됩니다.
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
// Works with TCL86, [Bill Moore (WPM) 3/16/2017]
// Requires: tcl86.dll and zlib1.dll from ActiveState Tcl placed in EXE directory
namespace TCL {
public delegate int Callback(List<string> args, out string result);
public interface IShell {
void AddFunction (string cmd, Callback F);
int Eval (string script, out string result);
}
public class Shell : IShell {
private IntPtr interp;
private Dictionary<string, Callback> DictCmds;
private TclDll.Tcl_ObjCmdProc DispatcherDelegate;
public Shell() {
DictCmds = new Dictionary<string, Callback>();
// Need Dispatcher Delegate for lifetime of object to avoid GC
// (Apparently C# automatically handles pinning of the pointers for delegates)
unsafe {
DispatcherDelegate = new TclDll.Tcl_ObjCmdProc(Dispatcher);
}
try {
interp = TclDll.Tcl_CreateInterp();
}
catch(Exception x) {
System.Windows.MessageBox.Show("TclDll.Tcl_CreateInterp failed 1\r\n" + x.ToString());
return;
}
if (interp == IntPtr.Zero) {
System.Windows.MessageBox.Show("TclDll.Tcl_CreateInterp failed 2");
return;
}
AddFunction("hello", Cmd_MyHello);
AddFunction("listfunt", Cmd_ListFunt);
return;
}
public int Eval(string script, out string ResultString) {
int ResultInt;
// Fix to allow multi-line scripts using either windows or linux formatted string..
// Remove Windows '\r' from Windows NewLine of '\r\n' leaving only '\n' Linux Newline
script = script.Replace("\r", "");
ResultInt = TclDll.Tcl_Eval(interp, script);
ResultString = TclDll.Helper_GetStringResult(interp);
return ResultInt;
}
public void AddFunction(string cmd, Callback F)
{
if (interp == null)
{
throw new SystemException ("ERROR: tcl_backend: interp is null\n");
}
DictCmds.Add(cmd, F);
TclDll.Helper_RegisterProc(interp, cmd, DispatcherDelegate);
}
private unsafe int Dispatcher(
IntPtr clientData,
IntPtr interp,
int objc,
TclDll.Tcl_Obj** objv)
{
List<string> args = TclDll.Helper_ObjvToList(objc, objv);
if (args.Count == 0) {
System.Windows.MessageBox.Show("EMPTY cmd dispatch");
return 0;
}
string cmd = args[0];
if (DictCmds.ContainsKey(cmd)) {
string result_string;
int result_code;
var F = DictCmds[cmd];
result_code = F(args, out result_string);
TclDll.Tcl_SetObjResult(interp, TclDll.Tcl_NewStringObj(result_string, -1));
return result_code;
}
return -1; //TclDll.TCL_OK;
}
public int Cmd_MyHello(List<string> args, out string result) {
//System.Windows.MessageBox.Show("MyHello!\n");
result="DONE WITH RESULT";
return 0;
}
public int Cmd_ListFunt(List<string> args, out string result) {
List<string> keys = new List<string>(DictCmds.Keys);
result = "";
foreach (string key in keys) {
result += key + "\r\n";
}
return 0;
}
} // Class Shell
public class TclDll {
public const int TCL_OK = 0;
[StructLayout(LayoutKind.Sequential)]
public struct Tcl_Obj
{
int refCount;
IntPtr bytes;
int length;
IntPtr typePtr;
Int64 value;
};
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate int Tcl_ObjCmdProc(
IntPtr clientData,
IntPtr interp,
int objc,
TclDll.Tcl_Obj** argv);
[DllImport(@"tcl86.dll", CallingConvention= CallingConvention.Cdecl)]
public static extern IntPtr Tcl_CreateObjCommand(
IntPtr interp,
[In, MarshalAs (UnmanagedType.LPStr)] string cmdName,
IntPtr proc,
IntPtr clientData,
IntPtr deleteProc
);
[DllImport(@"tcl86.dll")]
public unsafe static extern IntPtr Tcl_GetString(Tcl_Obj* obj);
[DllImport(@"tcl86.dll")]
public static extern IntPtr Tcl_CreateInterp();
[DllImport(@"tcl86.dll")]
public static extern int Tcl_Eval(
IntPtr interp,
[In, MarshalAs (UnmanagedType.LPStr)] string script);
[DllImport(@"tcl86.dll")]
public static extern IntPtr Tcl_GetObjResult(IntPtr interp);
[DllImport(@"tcl86.dll")]
public static extern int Tcl_SetObjResult(IntPtr interp, IntPtr objPtr);
[DllImport(@"tcl86.dll")]
public static extern IntPtr Tcl_NewStringObj(
[In, MarshalAs (UnmanagedType.LPStr)] string ObjName,
int length
);
public unsafe static string Helper_GetString(Tcl_Obj* obj) {
IntPtr b = TclDll.Tcl_GetString(obj);
string s = Marshal.PtrToStringAnsi(b);
return s;
}
public static string Helper_GetString(IntPtr obj) {
unsafe {
IntPtr b = TclDll.Tcl_GetString((Tcl_Obj*)obj);
string s = Marshal.PtrToStringAnsi(b);
return s;
}
}
public static string Helper_GetStringResult(IntPtr interp) {
IntPtr obj = Tcl_GetObjResult(interp);
if (obj == IntPtr.Zero) {
return "";
} else {
return Helper_GetString(obj);
}
}
public static unsafe List<string> Helper_ObjvToList(
int objc,
Tcl_Obj** objv)
{
var args = new List<string>();
for (int i=0; i < objc; i++)
{
string s = Helper_GetString(objv[i]);
args.Add(s);
}
return args;
}
public static unsafe void Helper_RegisterProc(IntPtr interp, string name, TclDll.Tcl_ObjCmdProc proc) {
Tcl_CreateObjCommand(
interp : interp,
cmdName : name,
proc : Marshal.GetFunctionPointerForDelegate(proc),
clientData : IntPtr.Zero,
deleteProc : IntPtr.Zero
);
}
}
} // Namespace
'Tcl & Tk > 팁 (Tip)' 카테고리의 다른 글
모든 위젯에 툴팁 달기 (0) | 2025.03.06 |
---|---|
Wish8x를 실행시킬 때 마다 특정 코드를 자동실행 (0) | 2025.03.06 |
특정 윈도우의 자식 윗젯들을 한꺼번에 없애기 (0) | 2025.03.06 |
음악에 쓰이는 음들의 진동수(주파수) 구하는 식 (0) | 2025.03.06 |
문자열로 비트맵 이미지 만들기 (0) | 2025.03.06 |