/////////////////////////////////////////////////////////////////////// /// <summary> /// This method is the starting point for threads created to manage a /// new Tcl form and interpreter. /// </summary> /// <param name="obj"> /// The Tcl client data to pass to the new Tcl form upon creation. /// </param> private static void CreateFormThreadStart( object obj /* in */ ) { try { // // NOTE: The data passed to this thread start routine // must be a string array or null. // IEnumerable <string> args = obj as IEnumerable <string>; TclForm form = null; try { // // NOTE: Create a new instance of the Tcl form, passing // the arguments we received from the other thread. // form = Create(args); // // NOTE: Upon success, show the form modally. // if (form != null) { Application.Run(form); } } finally { // // NOTE: Upon completion, successful or otherwise, dispose // of the form and its contained resources (including // the Tcl interpreter). // if (form != null) { form.Dispose(); form = null; } } } catch (Exception e) { ShowResult(ReturnCode.Error, e); } }
/////////////////////////////////////////////////////////////////////// #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); }