Author Topic: PyAcad.NET 0.6  (Read 2429 times)

0 Members and 1 Guest are viewing this topic.

TR

  • Guest
PyAcad.NET 0.6
« on: October 08, 2007, 11:31:12 PM »
I have released a new version of PyAcad.NET that people can mess with if they want. There is a binary available for AutoCAD 2008 but it should compile for 2007 fine.

I have given up on trying to register commands via python code for now. I have instead kept the original "pyfile" command and have included a new LispFunction called "runpyfile". I think I have done it correctly but hopefully someone here can take a look at the source and let me know.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: PyAcad.NET 0.6
« Reply #1 on: October 09, 2007, 10:51:39 AM »
Hi Tim,

I modified your source to handle lisp arguments correctly, see the comments in the code.
I also commented out

Code: [Select]
this.Terminate();
This could potentially make cad crash because .net modules can’t be unloaded

Code: [Select]
/*
PyAcadDotNet.cs
Copyright (c) 2007, Tim Riley (riltim@gmail.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list
  of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice, this list
  of conditions and the following disclaimer in the documentation and/or other materials
  provided with the distribution.

- Neither the name Tim Riley nor the names of its contributors may be used to
  endorse or promote products derived from this software without specific prior written
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;

using AcEd = Autodesk.AutoCAD.EditorInput;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

using IronPython.Hosting;

namespace PyAcadDotNet
{
  public class AcadInterface : IExtensionApplication
  {
    static internal AcEd.Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

    public void Initialize()
    {
      ed.WriteMessage("\nPyAcad.NET Loaded Successfully....");
    }

    public void Terminate()
    {
      // nothing to do here
      //this.Terminate();
    }

    internal delegate void AddReference(object assembly);

    [CommandMethod("pyfile", CommandFlags.Session)]
    static public void pythonfile()
    {
      try
      {
        OpenFileDialog ofd = new OpenFileDialog();
        ofd.Filter = "Python files (*.py)|*.py|All files (*.*)|*.*";
        ofd.ShowDialog();
        runpyfile(ofd.FileName);
      }
      catch (System.Exception e)
      {
        ed.WriteMessage(e.ToString());
      }
    }

    //Lisp example (runpyfile "C:\\print.py")
    //returns (T) on success (nil) on error
    [LispFunction("runpyfile")]
    static public ResultBuffer Lisprunpyfile(ResultBuffer resBuf)
    {
      TypedValue[] TvArray = resBuf.AsArray();
      ResultBuffer retBuf = new ResultBuffer();
      if (TvArray[0].TypeCode == (int)LispDataType.Text &&
          (string)TvArray[0].Value != string.Empty)
      {
        if (runpyfile((string)TvArray[0].Value) == true)
        {
          retBuf.Add(new TypedValue((int)LispDataType.T_atom));
        }
        else
        {
          retBuf.Add(new TypedValue((int)LispDataType.Nil));
        }
      }
      return retBuf;
    }

    //This now returns a bool for our lisp method
    static public bool runpyfile(string filename)
    {
      bool flag = false;
      using (PythonEngine engine = new PythonEngine())
      {
        using (AcadCommandLine myCommandLine = new AcadCommandLine())
        {
          try
          {
            // Create a new instance of PythonEngine and set variables.
            engine.AddToPath(Environment.CurrentDirectory);
            // Send Stdout and Stderr to the AutoCAD command line.
            engine.SetStandardOutput(myCommandLine);
            engine.SetStandardError(myCommandLine);
            engine.Import("clr");
            //lets load some AutoCAD assemblies.
            AddReference adr = engine.CreateMethod<AddReference>("clr.AddReference(assembly)");
            adr(typeof(BlockTableRecord).Assembly);
            adr(typeof(Editor).Assembly);

            // Run the file selected by the open file dialog box.
            //engine.ExecuteFile(ofd.FileName);
            CompiledCode cc = engine.CompileFile(filename);
            cc.Execute();
            flag = true;
          }
          catch (System.Exception e)
          {
            ed.WriteMessage(e.ToString());
          }
        }
      }
      return flag;
    }
  }

  //
  public class AcadCommandLine : Stream
  //Modified version of a class coded by Mike Stall.
  {
    public AcadCommandLine()
    {
      //constructor
    }

    #region unsupported Read + Seek members
    public override bool CanRead
    {
      get { return false; }
    }

    public override bool CanSeek
    {
      get { return false; }
    }

    public override bool CanWrite
    {
      get { return true; }
    }

    public override void Flush()
    {
      //
    }

    public override long Length
    {
      get { throw new NotSupportedException("Seek not supported"); } // can't seek
    }

    public override long Position
    {
      get
      {
        throw new NotSupportedException("Seek not supported");  // can't seek
      }
      set
      {
        throw new NotSupportedException("Seek not supported");  // can't seek
      }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
      throw new NotSupportedException("Reed not supported"); // can't read
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
      throw new NotSupportedException("Seek not supported"); // can't seek
    }

    public override void SetLength(long value)
    {
      throw new NotSupportedException("Seek not supported"); // can't seek
    }
    #endregion

    public override void Write(byte[] buffer, int offset, int count)
    {
      try
      {
        // Very bad hack: Ignore single newline char. This is because we expect the newline is following
        // previous content and we already placed a newline on that.
        AcEd.Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (count == 1 && buffer[offset] == '\n')
          return;

        StringBuilder sb = new StringBuilder();
        while (count > 0)
        {
          char ch = (char)buffer[offset];
          if (ch == '\n')
          {
            ed.WriteMessage(sb.ToString() + "\n");
            sb.Length = 0; // reset.
          }
          else if (ch != '\r')
          {
            sb.Append(ch);
          }

          offset++;
          count--;
        }
        if (sb.Length > 0)
          ed.WriteMessage(sb.ToString() + "\n");
      }
      catch (System.Exception e)
      {
        throw e;
      }
    }
  }
}


TR

  • Guest
Re: PyAcad.NET 0.6
« Reply #2 on: October 10, 2007, 10:46:11 AM »
Thanks Dan, once again you have bailed me out. I have updated the source code and released new binaries for 2008 which can be downloaded here. I have also included a README.txt in the download which should help people get it running.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: PyAcad.NET 0.6
« Reply #3 on: October 10, 2007, 10:56:02 AM »
Anytime, glad I could help  8-)