Author Topic: Can LispFunction return an atom ?  (Read 5228 times)

0 Members and 1 Guest are viewing this topic.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Can LispFunction return an atom ?
« on: October 25, 2008, 07:17:47 AM »
Hi,

I try to learn C#, creating some LISP extensions.
I read some post (here and there) about ResultBuffer to get the function arguments and to return the function result.
But this way the returned value is a list, i.e. (don't laught, I'm a complete beginner)

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

namespace DivLisp
{
    public class DivLisp
    {
        [LispFunction("div")]
        public ResultBuffer div(ResultBuffer args)
        {
            Array inputArgs = args.AsArray();
            double arg1 = Convert.ToDouble(((TypedValue)(inputArgs.GetValue(0))).Value);
            double arg2 = Convert.ToDouble(((TypedValue)(inputArgs.GetValue(1))).Value);
            ResultBuffer result = new ResultBuffer(new TypedValue((int)LispDataType.Double, (arg1 / arg2)));
            return result;
        }
    }
}

Commande: (div 10 3)
(3.33333)

Is there a way so that a LISP function which requieres arguments returns an atom (i.e. (div 10 3) returns 3.33333)
Speaking English as a French Frog

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Can LispFunction return an atom ?
« Reply #1 on: October 25, 2008, 08:17:55 AM »
Hi gile,

The LispFunction can return any of these types.

From the docs..
int
double
TypedValue
ResultBuffer
string
Point2d
Point3d
bool
void
ObjectId
SelectionSet


Since in C#, any type can be cast as an Object, you can just return an Object I.e

Code: [Select]
   [LispFunction("Lisp1")]
    public static Object Lisp1(ResultBuffer resBuf)
    {
      if (resBuf == null)
      {
        return false;
      }
      else
      {
        return true;
      }
    }

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Can LispFunction return an atom ?
« Reply #2 on: October 25, 2008, 08:37:24 AM »
Thank you very much Daniel, it was so simple !!!

This made me understand a little more how works C# and how many I have to learn...
Speaking English as a French Frog

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Can LispFunction return an atom ?
« Reply #3 on: October 25, 2008, 08:39:12 AM »
My pleasure  :-)

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Can LispFunction return an atom ?
« Reply #4 on: October 25, 2008, 09:16:31 AM »
So let’s break down how AutoCAD ObjectARX interprets atoms and lists. ObjectARX sees lisp types as a resbuf, essentially a container that has a type code and a value. I.e. (5000 . “Gile”)  where the type code describes the type of the value. In C#, the basic type for getting and returning values to lisp is called a TypedValue, it’s essentially the same as ObjectARX’s resbuf as it contains a type code and an Object.

So a real number would look like
(LispDataType.Double  .  3.33333)

And a String
(LispDataType.Text .  “Gile”) 

Keep in mind that C# knows nothing of parenthesis or the dot in the dotted pair.
When returning custom lists to lisp, you must explicitly construct them

I.e
(LispDataType.ListBegin . null)
(LispDataType.Double  .  3.33333)
(LispDataType.DottedPair . null)
(LispDataType.Text .  “Gile”) 
(LispDataType.ListEnd  , null)

Would return (3.3333 . “Gile”)  to lisp

A ResultBuffer in C# is a container for TypedValue types. Its unmanaged type is a resbuf or resbuf chain


an example

Code: [Select]
   [LispFunction("Lisp1")]
    public static Object Lisp1(ResultBuffer resBuf)
    {
      //++-- A new buffer to return
      ResultBuffer buf = new ResultBuffer();

      //make a list
      buf.Add(new TypedValue((int)LispDataType.ListBegin));
      buf.Add(new TypedValue((int)LispDataType.Double , 3.3333));
      buf.Add(new TypedValue((int)LispDataType.DottedPair));
      buf.Add(new TypedValue((int)LispDataType.Text, "Gile"));
      buf.Add(new TypedValue((int)LispDataType.ListEnd));

      return buf;
    }


Sorry, I haven’t had my coffee yet, so I’m probably not doing this well
« Last Edit: October 25, 2008, 09:38:01 AM by Daniel »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Can LispFunction return an atom ?
« Reply #5 on: October 25, 2008, 09:27:34 AM »
You can print out the TypedValues to see their codes and values

Code: [Select]
//(lisp2 '(1 2 3 4 5 6 7))
    [LispFunction("Lisp2")]
    public static Object Lisp2(ResultBuffer resBuf)
    {
      if (resBuf == null)
        return false;

      Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;

      //I like to convert the ResultBuffer to a List<>
      List<TypedValue> list = new List<TypedValue>(resBuf.AsArray());

      foreach (TypedValue atom in list)
      {
        ed.WriteMessage("\n{0}", atom);
      }

      return true;
    }


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8698
  • AKA Daniel
Re: Can LispFunction return an atom ?
« Reply #6 on: October 25, 2008, 09:51:05 AM »
I have attached some of the lisp stuff I was playing with a while back, maybe you can get something out of it.  :mrgreen:

Code: [Select]
   //(test1 1 1 "Hello" "Dude")
    [LispFunction("test1")]
    public static ResultBuffer test1(ResultBuffer args)
    {
      ResultBuffer retList = new ResultBuffer();
      try
      {
        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (args == null)
        {
          retList.AddErr("Null Argument");
          return retList;
        }

        if (args.GetCount() == 0)
        {
          retList.AddErr("To Few Arguments");
          return retList;
        }

        Func<TypedValue, bool>
          filter = x => x.TypeCode == (int)LispDataType.Text;

        var rlist = args.Where(filter);

        foreach (var e in rlist)
          retList.AddString(e.Value.ToString());


        if (retList.GetCount() == 0)
        {
          retList.AddNil();
          return retList;
        }

      }
      catch (System.Exception ex)
      {
        retList.AddErr(ex.Message);
      }
      return retList;
    }


    //(test2 "s" "a" "s" "a" "ad")
    [LispFunction("test2")]
    public static ResultBuffer test2(ResultBuffer args)
    {
      ResultBuffer retList = new ResultBuffer();
      try
      {

        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (args == null)
        {
          retList.AddErr("Null Argument");
          return retList;
        }

        if (args.GetCount() == 0)
        {
          retList.AddErr("To Few Arguments");
          return retList;
        }

        var query = from f in args
                    where f == new TypedValue((int)LispDataType.Text, "a")
                    select f;

        foreach (var e in query)
          retList.AddString((string)e.Value);

        if (retList.GetCount() == 0)
        {
          retList.AddNil();
          return retList;
        }

      }
      catch (System.Exception ex)
      {
        retList.AddErr(ex.Message);
      }
      return retList;
    }



« Last Edit: October 25, 2008, 10:05:05 AM by Daniel »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Can LispFunction return an atom ?
« Reply #7 on: October 25, 2008, 06:57:00 PM »
One more time thank you Daniel, I have to study all this :-o
Speaking English as a French Frog

Spike Wilbury

  • Guest
Re: Can LispFunction return an atom ?
« Reply #8 on: October 25, 2008, 07:11:20 PM »
One more time thank you Daniel, I have to study all this :-o

great for you.... welcome :)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Can LispFunction return an atom ?
« Reply #9 on: October 25, 2008, 07:14:18 PM »
Quote
convertor.png
:roll: :|
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.