依然是
上一篇文章的程序,换了C#写。
在Vczh Free Script 2.0的接口里面,我力求让C++和.NET两种语言的接口都趋于一致。目前达到了这个目标,C#仅仅比C++多了两个辅助函数。插件那一部分是相当难写啊。Vczh Free Script 2.0的C++接口允许插件和脚本交替调用。脚本引擎是本地代码,做到跟C#『交替调用』基本上是不可能的。上次看过一篇文章,在本地代码中调用托管代码,用了无穷多pin和com,于是我换了一种办法:使用Vczh Free Script 2.0提供的接口,用托管C++重新实现了一次插件。所幸代码不长,大概一千行左右吧。
下面是Vczh Free Script 2.0在C#中的使用方法。这个程序读入一个文件然后执行,返回结果或者输出错误信息以及出错所在行数周边的代码。
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using freescript_clr;
6
7 namespace FreeScript_CSharp
8 {
9 class VczhClass : FsClass
10 {
11 public VczhClass(FsPlugin Plugin)
12 : base(Plugin, "interpreter_debug")
13 {
14 }
15
16 public override FsePluginInvoke CallConstructor(int ClassID, FsObject[] Parameters, ref FsObject ErrorMessage, ref FsObject Result)
17 {
18 Console.WriteLine("VczhClass is creating");
19 AddExternalMember(ClassID, "MethodA", 0);
20 AddExternalMember(ClassID, "MethodB", 1);
21 AddExternalMember(ClassID, "MethodC", 2);
22 return FsePluginInvoke.Success;
23 }
24
25 public override FsePluginInvoke CallMember(int ClassID, int MemberID, FsObject[] Parameters, ref FsObject ErrorMessage, ref FsObject Result)
26 {
27 switch (GetMemberID(MemberID))
28 {
29 case 0:
30 Console.WriteLine("VczhClass::MethodA is invoking.");
31 break;
32 case 1:
33 Console.WriteLine("VczhClass::MethodB is invoking.");
34 break;
35 case 2:
36 Console.WriteLine("VczhClass::MethodC is invoking.");
37 break;
38 }
39 return FsePluginInvoke.Success;
40 }
41
42 public override void CallDestructor(int ClassID)
43 {
44 Console.WriteLine("VczhClass is destroying.");
45 }
46 }
47
48 class VczhConsole : FsPlugin
49 {
50 private FsObject FWrite = null;
51 private FsObject FWriteLine = null;
52 private FsObject FRead = null;
53 private FsObject FCollect = null;
54 private VczhClass FVczhClass = null;
55
56 public VczhConsole(FsEngine Engine, string CodePath)
57 : base(Engine, "interpretor")
58 {
59 FWrite = Engine.CreateExternalResource();
60 FWriteLine = Engine.CreateExternalResource();
61 FRead = Engine.CreateExternalResource();
62 FCollect = Engine.CreateExternalResource();
63 FVczhClass = new VczhClass(this);
64
65 GetEnvironment().SetFixedVariable("write", FWrite);
66 GetEnvironment().SetFixedVariable("writeln", FWriteLine);
67 GetEnvironment().SetFixedVariable("read", FRead);
68 GetEnvironment().SetFixedVariable("collect", FCollect);
69 GetEnvironment().SetFixedVariable("VczhClass", FVczhClass.GetCtor());
70 GetEnvironment().SetFixedVariable("apppath", Engine.CreateString(CodePath));
71 GetEnvironment().SetFixedVariable("vmpath", Engine.CreateString(System.AppDomain.CurrentDomain.BaseDirectory.ToString()));
72 }
73
74 public override FsePluginInvoke Invoke(int ID, FsObject[] Parameters, ref FsObject ErrorMessage, ref FsObject Result)
75 {
76 if (ID == FWrite.GetExternalID())
77 {
78 foreach (FsObject Param in Parameters)
79 {
80 Console.Write(Param.GetReadableString());
81 }
82 return FsePluginInvoke.Success;
83 }
84 else if (ID == FWriteLine.GetExternalID())
85 {
86 foreach (FsObject Param in Parameters)
87 {
88 Console.Write(Param.GetReadableString());
89 }
90 Console.WriteLine();
91 return FsePluginInvoke.Success;
92 }
93 else if (ID == FRead.GetExternalID())
94 {
95 foreach (FsObject Param in Parameters)
96 {
97 Console.Write(Param.GetReadableString());
98 }
99 Result = GetOwnedEngine().CreateString(Console.ReadLine());
100 return FsePluginInvoke.Success;
101 }
102 else if (ID == FCollect.GetExternalID())
103 {
104 GetOwnedEngine().CollectGarbage();
105 return FsePluginInvoke.Success;
106 }
107 else
108 {
109 return FsePluginInvoke.GiveUp;
110 }
111 }
112 }
113
114 class Program
115 {
116 static void Main(string[] args)
117 {
118 string AppPath = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
119 string CodePath = "";
120 if (args.Length == 0)
121 {
122 CodePath = AppPath + "Default.free";
123 }
124 else
125 {
126 CodePath = args[0];
127 AppPath = System.IO.Path.GetDirectoryName(CodePath);
128 }
129 if (AppPath[AppPath.Length - 1] != '\\')
130 {
131 AppPath += "\\";
132 }
133 string Code = (new System.IO.StreamReader(CodePath,Encoding.Default)).ReadToEnd();
134 FsEngine Engine = new FsEngine(false);
135 new VczhConsole(Engine, AppPath);
136
137 string ErrorMessage = "";
138 FsCodePage CodePage = Engine.Compile(Code,ref ErrorMessage);
139 if (CodePage!=null)
140 {
141 Engine.CreateTask(CodePage);
142 FsObject Result = Engine.CreateNull();
143
144 switch (Engine.Run(ref Result, ref ErrorMessage, false))
145 {
146 case FseRuntimeStatus.Exception:
147 {
148 Console.WriteLine("异常:[第" + (Engine.RuntimeErrorLine() + 1).ToString() + "行]" + Engine.RuntimeErrorMessage());
149 string[] Lines = Engine.RuntimeErrorCode().Split(new string[] { "\r\n" }, StringSplitOptions.None);
150 Console.WriteLine("==============================");
151 for (int i = Engine.RuntimeErrorLine() - 5; i <= Engine.RuntimeErrorLine() + 5; i++)
152 {
153 if (i >= 0 && i < Lines.Length)
154 {
155 if (i == Engine.RuntimeErrorLine())
156 {
157 Console.Write("* ");
158 }
159 else
160 {
161 Console.Write("- ");
162 }
163 Console.WriteLine(Lines[i]);
164 }
165 }
166 Console.WriteLine("==============================");
167 }
168 break;
169 case FseRuntimeStatus.Finish:
170 break;
171 default:
172 Console.WriteLine("未知错误。");
173 Engine.DestroyTask(Engine.GetTaskCount());
174 break;
175 }
176 }
177 else
178 {
179 Console.WriteLine(ErrorMessage);
180 }
181 Console.ReadLine();
182 }
183 }
184 }
posted on 2008-05-29 19:57
陈梓瀚(vczh) 阅读(2221)
评论(5) 编辑 收藏 引用 所属分类:
Vczh Free Script