我正在运行以下c#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Net;
using System.IO;
namespace TCLRunner
{
class Program
{
private static TclInterpreter interp;
static void Main(string[] args)
{
try
{
interp = new TclInterpreter();
//interp.evalScript(@"cd ..");
interp.evalScript(@"set a ""this is a""");
interp.evalScript(@"puts ""Free text""");
interp.evalScript(@"puts $a");
interp.evalScript(@"package require Tcl");
printResults();
interp.evalScript(@"package require http");
printResults();
//
//
// Shutdown and end connection
}
catch (Exception e)
{
Console.WriteLine("SocketException: {0}", e);
}
}
public static void printResults()
{
string result = interp.Result;
Console.WriteLine("Received: {0}", result);
}
}
public class TclAPI
{
[DllImport("tcl84.DLL")]
public static extern IntPtr Tcl_CreateInterp();
[DllImport("tcl84.Dll")]
public static extern int Tcl_Eval(IntPtr interp, string skript);
[DllImport("tcl84.Dll")]
public static extern IntPtr Tcl_GetObjResult(IntPtr interp);
[DllImport("tcl84.Dll")]
unsafe public static extern char* Tcl_GetStringFromObj(IntPtr tclObj, IntPtr length);
}
public class TclInterpreter
{
private IntPtr interp;
public TclInterpreter()
{
interp = TclAPI.Tcl_CreateInterp();
if (interp == IntPtr.Zero)
{
throw new SystemException("can not initialize Tcl interpreter");
}
}
public int evalScript(string script)
{
return TclAPI.Tcl_Eval(interp, script);
}
unsafe public string Result
{
get
{
IntPtr obj = TclAPI.Tcl_GetObjResult(interp);
if (obj == IntPtr.Zero)
{
return "";
}
else
{
return Marshal.PtrToStringAnsi((IntPtr)TclAPI.Tcl_GetStringFromObj(obj, IntPtr.Zero));
}
}
}
}
}
我得到以下输出:
自由文字 这是一个 收到:8.4 收到:无法找到包http
它怎么找不到http包?
当我在tclsh上手动尝试相同的操作时,它没有任何问题。
谢谢!
答案 0 :(得分:0)
您需要在调用Tcl_CreateInterp()
之前初始化库。通过使用已知的二进制运行的名称调用Tcl_FindExecutable
来初始化库,但可以相对安全地保留NULL
;这是其他事件(名称不当)的功能,例如设置查找其库的位置。
C#中的正确声明是这样的(尽管在这种情况下MarshalAs
属性是可选的):
[DllImport("tcl84.DLL")]
public static extern void Tcl_FindExecutable([MarshalAs(UnmanagedType.LPTStr)] string s);
你这样调用它,一次:
TclAPI.Tcl_FindExecutable(null);
(作为TclAPI
类中静态构造函数的一部分,这可能是最明智的。是的,它早期属于 。
如果这不起作用(我真的无法测试!),你必须set up some environment variables。关键一个是TCL_LIBRARY
,它会覆盖默认位置Tcl查找其支持脚本(包括http
包),您可能还需要设置TCLLIBPATH
。 (请注意,TCL_LIBRARY
主要是为了支持预安装测试,但有一段历史是由系统级别的 Python 设置其他不应该的系统。小心! )
同样,这必须在Tcl_CreateInterp()
电话之前完成。