/////////////////////////////////////////////////////////////////////// /// <summary> /// Attempts to wrap the Tcl manager host with one that captures the /// output from the internal DebugOps class. /// </summary> /// <param name="tclManager"> /// The Tcl manager object containing the host to wrap. /// </param> /// <param name="setup"> /// Non-zero if the Tcl manager host is being wrapped -OR- zero if it /// is being unwrapped. /// </param> private static void SetupManagerHost( ITclManager tclManager, /* in */ bool setup /* in */ ) { if (tclManager != null) { Interpreter interpreter = tclManager as Interpreter; if (interpreter != null) { ReturnCode hostCode; Result hostError = null; if (setup) { IHost host = null; hostCode = Utility.CopyAndWrapHost( interpreter, typeof(Class10), ref host, ref hostError); if (hostCode == ReturnCode.Ok) { interpreter.Host = host; return; } } else { hostCode = Utility.UnwrapAndDisposeHost( interpreter, ref hostError); if (hostCode == ReturnCode.Ok) { return; } } ShowResult(hostCode, hostError); } } }
/////////////////////////////////////////////////////////////////////// /// <summary> /// Disposes the Tcl manager object and then sets the value of its /// parameter to null. This method may only be called on the primary /// thread associated with the specified Tcl manager. /// </summary> /// <param name="manager"> /// The Tcl manager object to dispose and then set to null. /// </param> private static void DisposeManager( ref ITclManager tclManager /* in, out */ ) { if (tclManager != null) { // // NOTE: See if the Tcl manager supports IDisposable (it // should). If so, dispose it. // IDisposable disposable = tclManager as IDisposable; if (disposable != null) { disposable.Dispose(); disposable = null; } tclManager = null; } }
/////////////////////////////////////////////////////////////////////// /// <summary> /// Attempts to cancel the Tcl script in progress in the all Tcl /// interpreters managed by the specified Tcl manager object. This /// method may be called from any thread. /// </summary> /// <param name="strict"> /// Non-zero to return an error if the script in progress cannot be /// canceled for any of the Tcl interpreters. /// </param> /// <param name="error"> /// Upon failure, this parameter will be modified to contain an error /// message. /// </param> /// <returns> /// A standard Tcl return code. /// </returns> private static ReturnCode CancelAll( bool strict, /* in */ ref Result error /* out */ ) { lock (syncRoot) { if (forms != null) { try { foreach (TclForm form in forms.Keys) { if (form == null) // NOTE: Redundant? { continue; } // // NOTE: Grab the Eagle interpreter for this // form. // ITclManager tclManager = form.tclManager; if (tclManager == null) { continue; } // // NOTE: Grab the Tcl interpreter name for // this form. // string interpName = form.interpName; // // NOTE: Cancel the script being evaluated // for this form instance, if any. // ReturnCode cancelCode; Result cancelError = null; cancelCode = tclManager.CancelTclEvaluate( interpName, null, ref cancelError); if (cancelCode != ReturnCode.Ok) { if (strict) { // // NOTE: Strict mode means that we // stop upon encountering an // error and return that error // to the caller. // error = cancelError; return(cancelCode); } else { // // NOTE: Otherwise, just keep going // (after showing the error to // the user). // ShowResult(cancelCode, cancelError); } } } return(ReturnCode.Ok); } catch (Exception e) { error = e; } } else { error = "invalid forms collection"; } } return(ReturnCode.Error); }
/////////////////////////////////////////////////////////////////////// #region Static "Factory" Members public static TclForm Create( IEnumerable <string> args /* in */ ) { TclForm form = null; ITclManager tclManager = null; ReturnCode code = ReturnCode.Ok; Result result = null; try { form = new TclForm(); // // NOTE: Save the passed in command line arguments for // later. // form.args = args; // // NOTE: Create a new Eagle interpreter; currently, this // is necessary to use the Tcl integration features // of Eagle. // tclManager = Interpreter.Create(args, DefaultCreateFlags, ref result); if (tclManager != null) { // // NOTE: Attempt to use our custom Tcl manager host // implementation, if applicable. // SetupManagerHost(tclManager, true); // // NOTE: Automatically locate and select the "best" // available build of Tcl, if any. // code = tclManager.LoadTcl( DefaultFindFlags, DefaultLoadFlags, null, DefaultMinimumVersion, DefaultMaximumVersion, DefaultUnknownVersion, null, ref result); if (code == ReturnCode.Ok) { // // NOTE: Grab the name for the newly created // Tcl interpreter. // string interpName = result; // // NOTE: Create a new command object. This will // be used to demonstrate implementing a // Tcl command in managed code. // ICommand command = Class6.NewCommand("class6", new ClientData(form), DefaultCommandFlags); // // NOTE: Create a Tcl command bridging object. // This is used to translate inbound // native calls for a particular command // to a managed method call. // ITclEntityManager tclEntityManager = tclManager as ITclEntityManager; if (tclEntityManager != null) { code = tclEntityManager.AddTclBridge( command, interpName, command.Name, command.ClientData, false, false, ref result); } else { result = "invalid Tcl entity manager"; code = ReturnCode.Error; } // // NOTE: Did we successfully create the bridged // command? // if (code == ReturnCode.Ok) { // // NOTE: Save the created Eagle interpreter. // form.tclManager = tclManager; // // NOTE: Save the name of the created Tcl // interpreter. // form.interpName = interpName; // // NOTE: Keep track of this form in the // master collection. This collection // is primarily used when script // cancellation needs to be performed // for every Tcl interpreter we have // created. // lock (syncRoot) { if (forms != null) { forms.Add(form, null); } } } } } else { code = ReturnCode.Error; } } catch (Exception e) { result = e; code = ReturnCode.Error; } finally { if (code != ReturnCode.Ok) { // // NOTE: We failed to fully create the form. All // the resources we managed to successfully // create must be cleaned up now. // // NOTE: Dispose of the Eagle interpreter now // just in case the form does not have // the private variable set correctly. // DisposeManager(ref tclManager); /* throw */ if (form != null) { // // NOTE: If the form had an Eagle interpreter, // it should have already been disposed // (above) because we use the local // variable prior to setting the form // variable. To be sure that the now // disposed Eagle interpreter is not // used during form disposal, we need to // null out the form variable now. // form.tclManager = null; // // NOTE: Now, dispose any other resources held // by the form. // form.Dispose(); form = null; } } } if (code != ReturnCode.Ok) { ShowResult(code, result); } return(form); }