Author Topic: How to run lisp program except for SendStringToExcecute?  (Read 14988 times)

0 Members and 1 Guest are viewing this topic.

gswang

  • Newt
  • Posts: 117
How to run lisp program except for SendStringToExcecute?
« on: May 12, 2010, 08:26:17 AM »
How to run lisp program except for SendStringToExcecute?

i know 'eval' in lisp, but in .NET which function can eval lisp expression?

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8920
  • AKA Daniel
Re: How to run lisp program except for SendStringToExcecute?
« Reply #1 on: May 12, 2010, 08:59:28 AM »
have a look at this code

Code: [Select]
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices;

[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
  public static class Commands
  {
    [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl)]
    extern static int acedInvoke(IntPtr rbIn, out IntPtr rbOut);

    public static ResultBuffer Invoke(ResultBuffer rbIn)
    {
      IntPtr pRb = IntPtr.Zero;
      acedInvoke(rbIn.UnmanagedObject, out pRb);
      return DisposableWrapper.Create(typeof(ResultBuffer), pRb, true) as ResultBuffer;
    }

//    A sample lisp that takes a list as an argument
//   (defun thisisatest (a) (reverse a))
//   (vl-acad-defun 'thisisatest)

    [CommandMethod("doit")]
    public static void MyCommand()
    {

      // create a list to send, the first item in the list is the lisp func
      ResultBuffer rbOut = new ResultBuffer();
      rbOut.Add(new TypedValue((int)LispDataType.Text, "thisisatest"));

      // the argument
      rbOut.Add(new TypedValue((int)LispDataType.ListBegin));
      rbOut.Add(new TypedValue((int)LispDataType.Int32, 1));
      rbOut.Add(new TypedValue((int)LispDataType.Int32, 2));
      rbOut.Add(new TypedValue((int)LispDataType.Int32, 3));
      rbOut.Add(new TypedValue((int)LispDataType.Int32, 4));
      rbOut.Add(new TypedValue((int)LispDataType.ListEnd));

      //rbIn is the result from the lisp func
      ResultBuffer rbIn = Invoke(rbOut);

      List<TypedValue> list = new List<TypedValue>(rbIn.AsArray());

      list.ForEach(X =>
       AcAp.Application.DocumentManager.
       MdiActiveDocument.Editor.WriteMessage(X.Value.ToString()));
    }
  }
}


gswang

  • Newt
  • Posts: 117
Re: How to run lisp program except for SendStringToExcecute?
« Reply #2 on: May 14, 2010, 09:31:01 AM »
Thank you very much, Daniel! :-)

Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #3 on: May 14, 2010, 11:21:30 AM »
Do you think you could help me translate this code to vb.net?

I am learning .net but am not familiar enough with translation between cs and vb.

Peter

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8920
  • AKA Daniel
Re: How to run lisp program except for SendStringToExcecute?
« Reply #4 on: May 14, 2010, 11:42:33 AM »
Hi Peter

My VB is about worthless, about all I can do is use reflector. you will need to add the LispDataTypes back in.
I hope this helps you


Code: [Select]
Public Class Commands
    ' Methods
    <DllImport("acad.exe", CallingConvention:=CallingConvention.Cdecl)> _
    Private Shared Function acedInvoke(ByVal rbIn As IntPtr, <Out> ByRef rbOut As IntPtr) As Integer
    End Function

    Public Shared Function Invoke(ByVal rbIn As ResultBuffer) As ResultBuffer
        Dim pRb As IntPtr = IntPtr.Zero
        Commands.acedInvoke(rbIn.UnmanagedObject, pRb)
        Return TryCast(DisposableWrapper.Create(GetType(ResultBuffer), pRb, True),ResultBuffer)
    End Function

    <CommandMethod("doit")> _
    Public Shared Sub MyCommand()
        Dim rbOut As New ResultBuffer
        rbOut.Add(New TypedValue(5005, "thisisatest"))
        rbOut.Add(New TypedValue(5016))
        rbOut.Add(New TypedValue(5010, 1))
        rbOut.Add(New TypedValue(5010, 2))
        rbOut.Add(New TypedValue(5010, 3))
        rbOut.Add(New TypedValue(5010, 4))
        rbOut.Add(New TypedValue(5017))
        New List(Of TypedValue)(Commands.Invoke(rbOut).AsArray).ForEach(Function (ByVal X As TypedValue)
            Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(X.Value.ToString)
        End Function)
    End Sub

End Class


Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #5 on: May 14, 2010, 11:45:55 AM »
Thanks,

I will try to get it working.

Can you tell me about this reflector?

Is ia a separate program?

Is it built in to vs?

Are you using vs or an express version.

Peter

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8920
  • AKA Daniel
Re: How to run lisp program except for SendStringToExcecute?
« Reply #6 on: May 14, 2010, 11:54:36 AM »
It comes as a separate program or as a Visual studio add-on.. all you need is the free stand alone version. see http://www.red-gate.com/products/reflector/


Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #7 on: May 14, 2010, 05:09:59 PM »
Daniel,

I added the Autodesk.AutoCAD.Databaseservices to take care of the lisp data types but I have a problem with the nested function in the doit function.

The program has a syntax error on the New function and having trouble ith

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: How to run lisp program except for SendStringToExcecute?
« Reply #8 on: May 14, 2010, 08:50:34 PM »
Hello Peter,

could that be the difference between
new and New ??
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.

Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #9 on: May 17, 2010, 09:21:50 AM »
No tha didn't do it.

I need to understand several parts of the code shown above.

I guess the first thing is to understand the disposable wrapper for the unmanaged code.
I hope you guys can bear with me, while I ask what seems to be stupid questions.

Also I have vs2005 but it doesn't like being on the sme machine with vb2008 so it doesn't work.

I am trying to use vb2008 to write vb.net code.

I woul like to focus on creating an interface that calls arx functions from vb.net

Hence the question above.

The first part of the cde to understand is.

Code: [Select]
Public Shared Function Invoke(ByVal rbIn As ResultBuffer) As ResultBuffer
        Dim pRb As IntPtr = IntPtr.Zero
        Commands.acedInvoke(rbIn.UnmanagedObject, pRb)
        Return TryCast(DisposableWrapper.Create(GetType(ResultBuffer), pRb, True),ResultBuffer)
    End Function




Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #10 on: May 17, 2010, 09:23:25 AM »
Well I didn't mean to post yet, but to finish the question, do any of you have a good resource that would explain the components of the code above?

Peter

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8920
  • AKA Daniel
Re: How to run lisp program except for SendStringToExcecute?
« Reply #11 on: May 19, 2010, 02:12:16 AM »
Hi Peter,

It's really an advanced topic and there is not a lot of information out there, probably less in VB format as managed wrappers are written in C++/CLI.

A little bit about that block of code, AutoCAD's .NET API is just a wrapper around  C++/ARX. Every managed class has an underlying native class I.e. Line is a wrapper around AcDbLine and ResultBuffer wraps resbuf.  All the managed reference classes (Heap)  derive from a single class called DisposableWrapper, its job is to handle the storage, creation and deletion of underlying native classes. the DisposableWrapper class has a property, UnmanagedObject, which exposes a pointer that you can pass to native functions.  DisposableWrapper, has a create method that allows you to build a managed class from a native pointer.

Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #12 on: May 20, 2010, 02:44:21 PM »
Thanks for your help group,

I solved this puzzle yesterday and have the ability to load and run lisp routines from .NET, and not using the sendstringtoexecute or sendcommand methods.

I intend to share the material at AU, if I get my lecture approved.

If anyone is interested, I can tell you the trick.

Best Regards,

Peter


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8920
  • AKA Daniel
Re: How to run lisp program except for SendStringToExcecute?
« Reply #13 on: May 28, 2010, 08:43:44 PM »
What's the trick?

Peter Jamtgaard

  • Guest
Re: How to run lisp program except for SendStringToExcecute?
« Reply #14 on: May 29, 2010, 08:34:34 AM »
Actually I found several methods.

They are acedInvokeLISP entry point, acedEvaluateLISP entry point and the VL16.tlb method
(the last of which according to TonyT has bugs when called repeatedly in a loop)

Peter