Call Lisp command via .NET C#

Hello,

Let's assume I have a LISP:

(defun c:drawMultipleCircles ()
(setq center1 '(0 0 0))
(setq radius1 10)
(c:mycircle center1 radius1)

(defun c:mycircle (p r)
(command "CIRCLE" p r)
(princ)
)

I would like to call this command via .NET C#. However, I can't do this using "SendStringToExecute" or "Editor.Command" as SendStringToExecute and Editor.Command only occur after my method has finished.

I saw something on some forums about Application.Invoke(), which apparently does not exist in Bricscad.

Something like this:

ResultBuffer args = new ResultBuffer(new TypedValue((int)LispDataType.Text, "c:hello"));
ResultBuffer result = Application.Invoke(args);

I would like your opinion on how one could call a LISP in a way that allows for greater control.
Because with SendStringToExecute and Editor.Command, I did not achieve an interesting result.

Thank you.

Comments

  • Its_Alive
    edited May 7

    It's in there, Bricscad.Global.Editor.invoke

  • Hello @Its_Alive,

    Thank you for your response; it worked partially, but I am experiencing a BUG and I don't know the reason for it.

    Here is my Lisp:

    (defun c:mycircle (p r)
      (command "CIRCLE" p r)
      (princ)
    )
    
    

    And here is my C# code:

    [CommandMethod("W11")]
    public static void CreateW11()
    {
        var args = new ResultBuffer(
           new TypedValue((int)LispDataType.Text, "c:mycircle"),
           new TypedValue((int)LispDataType.Point3d, new Point3d(500, 500, 0)),
           new TypedValue((int)LispDataType.Int32, 250));
        Bricscad.Global.Editor.Invoke(args);
    }
    
    

    It functions, however, the document becomes buggy. For each action, I need to use the Regen command, similar to the error when a Transaction remains open.
    If I try to delete an object, after the command it still shows the object, then I need Regen and then the object disappears, and so it is for each action of drawing or editing an entity.

    Am I missing something?
    I've already placed it within a Transaction, but it still causes the same bug.

  • Not sure, I really don’t use .NET, but I do see an issue, you need to end the ResultBuffer with a LispDataType None

    so, I think that would something like new TypedValue((int)LispDataType.None, 0));

    Invoke should also return a value that you can check, your lisp function should return T or nil or something so the the .NET side knows what happened

  • Thank you @Its_Alive,

    I really don't know how to make this work. I tried with None, Nil, modified the Lisp, but it still shows the same error. I tested other Lisps and nothing, same problem, after the execution of Bricscad.Global.Editor.Invoke() it bugs and doesn’t update the drawing with the modifications...
    The issue seems to be with the parameters passed. If there are no parameters, this error does not occur.

    What I did to "make it work" was a workaround:

    (defun c:mycircle (p r)
    (command "CIRCLE" p r)
    ;(command "mycircleEnd") -> if added here directly or called in C# code, it's the same
    (princ)
    )

    (defun c:mycircleEnd ()
    (princ "End")
    )

    C# code:

    var argsCircle = new ResultBuffer(
    new TypedValue((int)LispDataType.Text, "c:mycircle"),
    new TypedValue((int)LispDataType.Point3d, new Point3d(0, 0, 0)),
    new TypedValue((int)LispDataType.Int32, 250)
    );

    Bricscad.Global.Editor.Invoke(argsCircle);
    Bricscad.Global.Editor.Invoke(new ResultBuffer(
    new TypedValue((int)LispDataType.Text, "mycircleEnd"))); // this "removes" the error

    There must be something I am forgetting to load or some function is missing, because when another Lisp without parameters is executed, it "fixes" this bug.

    If anyone knows what it could be, I would appreciate it.

  • Its_Alive
    edited May 8

    I tested with AutoCAD, it seems calling a command in this way may not work

    error: AutoCAD command rejected: "CIRCLE", entmake works

    Also as I noted earlier, you must terminate the result buffer

  • Its_Alive
    edited May 8
    import traceback
    from pyrx_imp import Rx, Ge, Db, Ap, Ed, Gi, Gs
    
    def PyRxCmd_calllisp():
        try:
            args = [(Rx.LispType.kText, "c:mycircle"),
                    (Rx.LispType.kPoint3d, Ge.Point3d(0, 0, 0)),
                    (Rx.LispType.kDouble, 10),
                    (Rx.LispType.kNone,0) ] #you must end the result buffer
            rbout = Ed.Core.invoke(args)
            print(rbout)
        except Exception as err:
            traceback.print_exception(err)
           
    
    (defun c:mycircle (p r)
    (entmake (list(cons 0 "CIRCLE") (cons 62 3) (cons 10 p) (cons 40 r)))
    )

  • code formatting is horrible

  • Thank you @Its_Alive,

    My knowledge of Lisp is limited.
    But what I noticed is that the "command" function doesn't work, but the "entmake" function does.
    That's the only difference I noticed.

    I ran the tests with the same C# code but with the difference in the Lisp.

    C# code:

    var argsCircle = new ResultBuffer(
    new TypedValue((int)LispDataType.Text, "c:mycircleEnt"),
    new TypedValue((int)LispDataType.Point3d, new Point3d(0, 0, 0)),
    new TypedValue((int)LispDataType.Double, 250),
    new TypedValue((int)LispDataType.None, 0)
    );

    Bricscad.Global.Editor.Invoke(argsCircle);

    Correct Lisp code:

    (defun c:mycircleEnt (p r)
    (entmake (list (cons 0 "CIRCLE") (cons 62 3) (cons 10 p) (cons 40 r)))
    )

    Lisp code that doesn't work:

    (defun c:mycircle2 (p r)
    (command "CIRCLE" p r)
    (princ)
    )

    The difference lies in the "command" function. I'm not sure, but if "command" makes a change in the database, it causes the issue. Unfortunately, I couldn't find any information to confirm this theory.

    Anyway, @Its_Alive, thank you once again for your help and time.

    Best regards,Eduardo