Author Topic: ResultBuffers and LispFunction()  (Read 19382 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
ResultBuffers and LispFunction()
« on: April 04, 2007, 11:32:35 PM »
This is my first sojourn into LispFunction() land

.. surprising, heh !

Testing in AC2008
Anyone see anything blatantly askew about this ?
Code: [Select]
using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;

using System.Text;
using System.IO;

[assembly: CommandClass(typeof(ClassLibrary.kdubClass70405))]

namespace ClassLibrary
{
    /// <summary>
    /// Summary description for kdubClass.
    /// </summary>
    public class kdubClass70405
    {
        public kdubClass70405()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        //
        // From adscodes.h :
        //
        const int RTNONE = 5000; /* No result */
        const int RTREAL = 5001; /*Real number */
        const int RTPOINT = 5002; /* 2D point X and Y only */
        const int RTSHORT = 5003; /* Short integer */
        const int RTANG = 5004; /* Angle */
        const int RTSTR = 5005; /* String */
        const int RTENAME = 5006; /* Entity name */
        const int RTPICKS = 5007; /* Pick set */
        const int RTORINT = 5008; /* Orientation */
        const int RT3DPOINT = 5009; /* 3D point - X, Y, and Z */
        const int RTLONG = 5010; /* Long integer */
        const int RTVOID = 5014; /* Blank symbol */
        const int RTLB = 5016; /* list begin */
        const int RTLE = 5017; /* list end */
        const int RTDOTE = 5018; /* dotted pair */
        const int RTNIL = 5019; /* nil */
        const int RTDXF0 = 5020; /* DXF code 0 for ads_buildlist only */
        const int RTT = 5021; /* T atom */
        const int RTRESBUF = 5023; /* resbuf */
        const int RTMODELESS = 5027; /* interrupted by modeless dialog */

        //
        //
        [LispFunction("TestFolder")]
        public object TestFolder(ResultBuffer buff)
        {
            Array args = buff.AsArray();
            string path = Convert.ToString(((TypedValue)(args.GetValue(0))).Value);
            ResultBuffer resBuff = new ResultBuffer();
            if (File.Exists(path))
            {
                return new TypedValue(RTSTR, "Feed me a FolderName, Dummy !");
            }
            if (!(Directory.Exists(path)))
            {
                return new TypedValue(RTSTR, "Root Folder does not Exist");
            }
            string[] subdirectoryEntries = Directory.GetDirectories(path);
            foreach (string subDirName in subdirectoryEntries)
                resBuff.Add(new TypedValue(
                    RTSTR,
                    subDirName.Substring(subDirName.LastIndexOf("\\") + 1)
                    ));
            if (subdirectoryEntries.Length == 0)
                return new TypedValue(RTSTR, "No Files");
            else
                return resBuff;
        }
    }
}

Code: [Select]
(testfolder "c:\\")
(testfolder "T:\\CONFIG")

(testfolder "c:\\Rubish")
(testfolder "c:\\ACAD2008\\ACAD.EXE")

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #1 on: April 04, 2007, 11:40:03 PM »
Should this:

Code: [Select]
Array args = buff.AsArray();

be this:

Code: [Select]
TypedValue[] tvs = buff.AsArray();

???

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #2 on: April 04, 2007, 11:51:24 PM »
Probably better Glenn :-)
though it did work ..


(testfolder "C:\\CTA17_SteelTools")
(testfolder "T:\\CONFIG")
(testfolder "c:\\Rubish")
(testfolder "c:\\ACAD2008\\ACAD.EXE")
(testfolder "c:\\Program Files\\This is just a Dummy.XML")

("Blocks" "Hotkeys2007" "MenuAndStartup" "Support")
"No Files"
"Root Folder does not Exist"
"Feed me a FolderName, Dummy !"
"Root Folder does not Exist"
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #3 on: April 05, 2007, 12:09:50 AM »
This is easier to read to mine own eyes:
Code: [Select]
[LispFunction("TestFolder")]
public object TestFolder(ResultBuffer buff) {
TypedValue[] args = buff.AsArray();
string path = ((TypedValue)args.GetValue(0)).Value as string;
if(path == null)
return new TypedValue(RTSTR, string.Empty);
ResultBuffer resBuff = new ResultBuffer();
if(File.Exists(path))
return new TypedValue(RTSTR, "Feed me a FolderName, Dummy !");

if(!(Directory.Exists(path)))
return new TypedValue(RTSTR, "Root Folder does not Exist");

string[] subdirectoryEntries = Directory.GetDirectories(path);
if (subdirectoryEntries == null || subdirectoryEntries.Length == 0)
return new TypedValue(RTSTR, "No Files");

foreach(string subDirName in subdirectoryEntries)
resBuff.Add(new TypedValue(
RTSTR,
subDirName.Substring(subDirName.LastIndexOf("\\") + 1)
));

return resBuff;
}

Personal preference is all...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #4 on: April 05, 2007, 12:28:47 AM »
ahhhhh, the old "do we need the braces" discussion :D

The 'or' conditional IS better ..thanks Glenn
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #5 on: April 05, 2007, 12:35:48 AM »
... and of course, the "No Files" message should be "No Folders"   duh!
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #6 on: April 05, 2007, 12:40:01 AM »
Braces, schmaces :)

WRT the OR, the reason I do this is defensive. I have had some functions in the framework return a valid instance of a return type, even though I would have expected them to return null when they failed. The "IF OR" will use short circuit evaluation - ie It will evaulate the null condition first and if true, bail. It will only move onto the next test if that fails. It then checks the Length in this case. Imagine what would happen if you had a null instance and tried using the Length property? Big fat exception. So the order of the tests is the improtant part.

... and of course, the "No Files" message should be "No Folders"   duh!

Yes it should.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #7 on: April 05, 2007, 12:44:00 AM »
...........The "IF OR" will use short circuit evaluation - ............. Big fat exception..............

Yep, I bashed my head on the keyboard when I saw your alternative.
... may have picked it up tomorrow when I re-wrote it :-D
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: ResultBuffers and LispFunction()
« Reply #8 on: April 05, 2007, 08:10:51 AM »
Awesome Kerry!

I like to stick the TypedValue struct in a list instead of an array (opinion)

Code: [Select]
List<TypedValue>args= new List<TypedValue>(buff.AsArray());

also have a look at the LispDataType enum

Code: [Select]
resBuff.Add(new TypedValue((int)LispDataType.yourtype , yourvalue));


edit: ps I like the way Kerry's code is layed out better.
« Last Edit: April 05, 2007, 09:12:03 AM by Danielm103 »

TonyT

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #9 on: April 05, 2007, 04:53:08 PM »

Code: [Select]
        //
        // From adscodes.h :
        //
        const int RTNONE = 5000; /* No result */
        const int RTREAL = 5001; /*Real number */
        const int RTPOINT = 5002; /* 2D point X and Y only */
        const int RTSHORT = 5003; /* Short integer */
        const int RTANG = 5004; /* Angle */
        const int RTSTR = 5005; /* String */
        const int RTENAME = 5006; /* Entity name */
        const int RTPICKS = 5007; /* Pick set */

Have a look at the LispDataType enum
« Last Edit: April 05, 2007, 04:54:14 PM by TonyT »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #10 on: April 05, 2007, 09:02:36 PM »

Also, .. is one supposed to use a
Code: [Select]
[assembly: CommandClass(typeof(ClassLibrary.classname))]
on a
Code: [Select]
[LispFunction("function")]?
I do it all the time, I just don't want to explode other peoples computers

I don't know Daniel ... I'll have to do some more reading :-)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #11 on: April 05, 2007, 09:03:40 PM »

Code: [Select]
        //
        // From adscodes.h :
//..............................
 

Have a look at the LispDataType enum

Thanks Tony, I will.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #12 on: April 05, 2007, 09:07:41 PM »
Ahhhhh .. playtime
Code: [Select]
public enum LispDataType
{
    Angle = 0x138c,
    DottedPair = 0x139a,
    Double = 0x1389,
    Int16 = 0x138b,
    Int32 = 0x1392,
    ListBegin = 0x1398,
    ListEnd = 0x1399,
    Nil = 0x139b,
    None = 0x1388,
    ObjectId = 0x138e,
    Orientation = 0x1390,
    Point2d = 0x138a,
    Point3d = 0x1391,
    SelectionSet = 0x138f,
    T_atom = 0x139d,
    Text = 0x138d,
    Void = 0x1396
}
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gilseorin

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #13 on: April 06, 2007, 11:38:28 AM »
I introduce my first LispFuction.

Code: [Select]
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System.Math;

public class GILSclass1
{
 const int RTREAL = 5001;

 [LispFuction("PolarPoint")]
 public ResultBuffer DotNetfunction(ResultBuffer rbfArgs)
 {
   Array arInputArgs;
   Point3d co;
   double ang;
   double dst;
   arInputArgs = rbfArgs.AsArray;
   co = ((TypedValue)(arInputArgs.GetValue(0))).Value;
   ang = ((TypedValue)(arInputArgs.GetValue(1))).Value;
   dst = ((TypedValue)(arInputArgs.GetValue(2))).Value;
   double x = co.X;
   double y = co.Y;
   double z = co.Z;
   double px = dst * Cos(ang);
   double py = dst * Sin(ang);
   double pz = z;
   double ox = px + x;
   double oy = py + y;
   double oz = pz;
   ResultBuffer rbfResult;
   rbfResult = new ResultBuffer(new TypedValue(System.Convert.ToInt32(5001), ox), _
                                new TypedValue(System.Convert.ToInt32(5001), oy), _
                                new TypedValue(System.Convert.ToInt32(5001), oz));
   return rbfResult;
 }
}

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #14 on: April 06, 2007, 10:59:34 PM »
Ahhhhh .. playtime
Code: [Select]
public enum LispDataType
{
    Angle = 0x138c,
    DottedPair = 0x139a,
    Double = 0x1389,
    Int16 = 0x138b,
    Int32 = 0x1392,
    ListBegin = 0x1398,
    ListEnd = 0x1399,
    Nil = 0x139b,
    None = 0x1388,
    ObjectId = 0x138e,
    Orientation = 0x1390,
    Point2d = 0x138a,
    Point3d = 0x1391,
    SelectionSet = 0x138f,
    T_atom = 0x139d,
    Text = 0x138d,
    Void = 0x1396
}

Are you still playing?

I have time to play a little, one more time in the C# stuff, I tried to complete one my functions I have in C++, and implement what Tony recommended, just the last part still not completed, the dotted pair list output build (I don't need to much lisp functions anymore, but it is always good to know and learn more!).

The arguments requires to be something like: (setq lst (list '("one" 2) '("one" 3) '("two" 4) '("two" 5)))
Command: (summation lst)

First not using LispDataType and not returning a list, just WriteMessage()
Code: [Select]
[LispFunction("Summation")]
static public void summation(ResultBuffer args)
{
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    Dictionary<string, short> openWith = new Dictionary<string, short>();
    IEnumerator it = args.GetEnumerator();
    while (it.MoveNext())
    {
        short ad = 0, num = 0;
        TypedValue val = (TypedValue)it.Current;
        // ignore start or end of list
        short RTLB = 5016, RTLE = 5017;
        if (val.TypeCode == RTLB || val.TypeCode == RTLE) { }
        else
        {
            string sKey = val.Value.ToString();
            it.MoveNext();
            val = (TypedValue)it.Current;
            num = (short)val.Value;
            try
            {
                openWith.Add(sKey, num);
            }
            catch (ArgumentException)
            {
                if (openWith.TryGetValue(sKey, out ad))
                {
                    num = (short)(num + ad);
                    openWith.Remove(sKey);
                    openWith.Add(sKey, num);
                }
            }
        }
    }
    foreach (KeyValuePair<string, short> kvp in openWith)
    {
        ed.WriteMessage("\nKey = {0}, Value = {1}",
            kvp.Key, kvp.Value);
    }
}

Next one, trying to implement LispDataType and to return a ResultBuffer
Code: [Select]
[LispFunction("SummationR")]
static public void summationr(ResultBuffer args)
{
    ResultBuffer res = new ResultBuffer();
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    Dictionary<string, short> openWith = new Dictionary<string, short>();
    IEnumerator it = args.GetEnumerator();
    while (it.MoveNext())
    {
        short ad = 0, num = 0;
        TypedValue val = (TypedValue)it.Current;
        if ((LispDataType)val.TypeCode != LispDataType.ListBegin && (LispDataType)val.TypeCode != LispDataType.ListEnd)
        {
            string sKey = val.Value.ToString();
            it.MoveNext();
            val = (TypedValue)it.Current;
            num = (short)val.Value;
            try
            {
                openWith.Add(sKey, num);
            }
            catch (ArgumentException)
            {
                if (openWith.TryGetValue(sKey, out ad))
                {
                    num = (short)(num + ad);
                    openWith.Remove(sKey);
                    openWith.Add(sKey, num);
                }
            }
        }
    }
    foreach (KeyValuePair<string, short> kvp in openWith)
    {
        ed.WriteMessage("\nKey = {0}, Value = {1}", kvp.Key, kvp.Value);
        //TypedValue TV = new TypedValue();
        //LispDataType LSPT = new LispDataType.
        //res.Add()
    }
}

Thanks!