Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Вильдар от 03-03-2016, 10:36:20

Название: Вызов лисп функции с передачей списка точечных пар
Отправлено: Вильдар от 03-03-2016, 10:36:20
Всем привет,
Можно ли вызвать лисп функцию и передать ей список точечных пар?
Передать нужно примерно такой список:
Код - Auto/Visual Lisp [Выбрать]
  1. (("Name" . "Test")("Length" . 1000))
Тестовый пример:
Код - C# [Выбрать]
  1.         [CommandMethod("TestInvoke")]
  2.         public void TestInvoke()
  3.         {
  4.             ResultBuffer rb = new ResultBuffer( new TypedValue[]
  5.                {
  6.                    new TypedValue((int)LispDataType.Text, "TestLispFunc"),
  7.                    new TypedValue((int)LispDataType.ListBegin),
  8.                    new TypedValue((int)LispDataType.ListBegin),
  9.                    new TypedValue((int)LispDataType.Text, "Name"),
  10.                    new TypedValue((int)LispDataType.Text, "Test"),
  11.                    new TypedValue((int)LispDataType.DottedPair),
  12.                    new TypedValue((int)LispDataType.ListBegin),
  13.                    new TypedValue((int)LispDataType.Text, "Length"),
  14.                    new TypedValue((int)LispDataType.Int32, "1000"),
  15.                    new TypedValue((int)LispDataType.DottedPair),
  16.                    new TypedValue((int)LispDataType.ListEnd)
  17.                }
  18.             );            
  19.             var res = Application.Invoke(rb);
  20.         }
Вызываемая лисп функция
Код - Auto/Visual Lisp [Выбрать]
  1. (defun TestLispFunc(p)
  2.         (princ p)              
  3. )
  4. (vl-acad-defun 'TestLispFunc)

В таком виде выводится ошибка:
Цитировать
Команда: TESTINVOKE
; ошибка: extra :LE element in reslist: (:LB :LB "Name" "Test" :DOTE :LB "Length" 1000 :DOTE :LE)
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Александр Ривилис от 03-03-2016, 10:39:33
Попробуй окаймить его его еще в ListBegin/ListEnd, т.е. вместо
Код - Auto/Visual Lisp [Выбрать]
  1.     (("Name" . "Test")("Length" . 1000))
передавать
Код - Auto/Visual Lisp [Выбрать]
  1.     ((("Name" . "Test")("Length" . 1000)))
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Вильдар от 03-03-2016, 10:42:30
Т.е. так?
Код - C# [Выбрать]
  1.                    new TypedValue((int)LispDataType.Text, "TestLispFunc"),
  2.                    new TypedValue((int)LispDataType.ListBegin),
  3.                    new TypedValue((int)LispDataType.ListBegin),
  4.                    new TypedValue((int)LispDataType.ListBegin),
  5.                    new TypedValue((int)LispDataType.Text, "Name"),
  6.                    new TypedValue((int)LispDataType.Text, "Test"),
  7.                    new TypedValue((int)LispDataType.DottedPair),
  8.                    new TypedValue((int)LispDataType.ListBegin),
  9.                    new TypedValue((int)LispDataType.Text, "Length"),
  10.                    new TypedValue((int)LispDataType.Int32, "1000"),
  11.                    new TypedValue((int)LispDataType.DottedPair),
  12.                    new TypedValue((int)LispDataType.ListEnd),
  13.                    new TypedValue((int)LispDataType.ListEnd)
Такой вывод:
Цитировать
Команда: TESTINVOKE
; ошибка: extra :LE element in reslist: (:LB :LB :LB "Name" "Test" :DOTE :LB "Length" 1000 :DOTE :LE :LE)
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Александр Ривилис от 03-03-2016, 10:48:07
А если убрать последний new TypedValue((int)LispDataType.ListEnd) ?
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Вильдар от 03-03-2016, 10:51:43
Убрал последний ListEnd
Код - C# [Выбрать]
  1.                    new TypedValue((int)LispDataType.Text, "TestLispFunc"),
  2.                    new TypedValue((int)LispDataType.ListBegin),
  3.                    new TypedValue((int)LispDataType.ListBegin),
  4.                    new TypedValue((int)LispDataType.ListBegin),
  5.                    new TypedValue((int)LispDataType.Text, "Name"),
  6.                    new TypedValue((int)LispDataType.Text, "Test"),
  7.                    new TypedValue((int)LispDataType.DottedPair),
  8.                    new TypedValue((int)LispDataType.ListBegin),
  9.                    new TypedValue((int)LispDataType.Text, "Length"),
  10.                    new TypedValue((int)LispDataType.Int32, "1000"),
  11.                    new TypedValue((int)LispDataType.DottedPair),
  12.                    new TypedValue((int)LispDataType.ListEnd)
Вывод:
Цитировать
Команда: TESTINVOKE
; ошибка: extra :LE element in reslist: (:LB :LB :LB "Name" "Test" :DOTE :LB "Length" 1000 :DOTE :LE)
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Алексей Кулик от 03-03-2016, 12:03:31
Я, конечно, ни разу не спец по .NET, но, по-моему, сама структура создаваемого ResultBuffer какая-то "не та". Разве ListBegin и ListEnd не должны образовывать пары? Да и точечная пара, кажется, должна организовываться по принципу
Код - C# [Выбрать]
  1. rb.Add(new TypedValue((int)LispDataType.ListBegin));
  2. rb.Add(new TypedValue((int)LispDataType.Text, "Text"));
  3. rb.Add(new TypedValue((int)LispDataType.DottedPair));
  4. rb.Add(new TypedValue((int)LispDataType.Text, "Name"));
  5. rb.Add(new TypedValue((int)LispDataType.ListEnd));
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Александр Ривилис от 03-03-2016, 12:17:29
Я, конечно, ни разу не спец по .NET, но, по-моему, сама структура создаваемого ResultBuffer какая-то "не та". Разве ListBegin и ListEnd не должны образовывать пары? Да и точечная пара, кажется, должна организовываться по принципу
Код - C# [Выбрать]
  1. rb.Add(new TypedValue((int)LispDataType.ListBegin));
  2. rb.Add(new TypedValue((int)LispDataType.Text, "Text"));
  3. rb.Add(new TypedValue((int)LispDataType.DottedPair));
  4. rb.Add(new TypedValue((int)LispDataType.Text, "Name"));
  5. rb.Add(new TypedValue((int)LispDataType.ListEnd));
Как ни странно, но ты прав, Лёша. :) Хотя в ObjectARX не так (и последовательность у vildar82 правильная). Честно говоря как они это сделали - ума не приложу. Зная как в ObjectARX мне бы в голову не пришло проверять то как ты написал (т.е. чисто лисповский вариант).

Работает вот такой код:

Код - C# [Выбрать]
  1. [CommandMethod("TestInvoke")]
  2. public void TestInvoke()
  3. {
  4.   ResultBuffer rb = new ResultBuffer(new TypedValue[]
  5.     {
  6.       new TypedValue((int)LispDataType.Text, "TestLispFunc"),
  7.       new TypedValue((int)LispDataType.ListBegin),
  8.       new TypedValue((int)LispDataType.ListBegin),
  9.       new TypedValue((int)LispDataType.Text, "Name"),
  10.       new TypedValue((int)LispDataType.DottedPair),
  11.       new TypedValue((int)LispDataType.Text, "Test"),
  12.       new TypedValue((int)LispDataType.ListEnd),
  13.       new TypedValue((int)LispDataType.ListBegin),
  14.       new TypedValue((int)LispDataType.Text, "Length"),
  15.       new TypedValue((int)LispDataType.DottedPair),
  16.       new TypedValue((int)LispDataType.Int16, 1000),
  17.       new TypedValue((int)LispDataType.ListEnd),
  18.       new TypedValue((int)LispDataType.ListEnd)
  19.     }
  20.   );
  21.   var res = Application.Invoke(rb);
  22. }

vildar82
Обрати внимание на отличие строки с число 1000 у меня в коде и у тебя.
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Дима_ от 03-03-2016, 12:56:50
Забавно, но это действительно похоже на какой-то баг через который таки работает. Если передать .Net лисп-функции точечную пару, то на входе получится синтаксис как у vildar82, у Алексея-же передается список "замаскированный" под пару. Интересно если вызвать таким образом, с аргументом точечной пары из двух строк, что-то типа:
Код - Auto/Visual Lisp [Выбрать]
  1. (defun test(x) (strcat (car x) (cdr x)))
Отработает?? - если да то "обход" найден.
Название: Re: Вызов лисп функции с передачей списка точечных пар
Отправлено: Александр Ривилис от 03-03-2016, 13:19:01
(defun test(x) (strcat (car x) (cdr x)))
Код - Auto/Visual Lisp [Выбрать]
  1. (defun test(x)
  2.   (print (strcat (car (car x)) " . " (cdr (car x))))
  3. )
  4. (vl-acad-defun 'test)

Код - C# [Выбрать]
  1. [CommandMethod("TestInv1")]
  2. public void TestInv1()
  3. {
  4.   ResultBuffer rb = new ResultBuffer(new TypedValue[]
  5.    {
  6.      new TypedValue((int)LispDataType.Text, "Test"),
  7.      new TypedValue((int)LispDataType.ListBegin),
  8.      new TypedValue((int)LispDataType.ListBegin),
  9.      new TypedValue((int)LispDataType.Text, "Name"),
  10.      new TypedValue((int)LispDataType.DottedPair),
  11.      new TypedValue((int)LispDataType.Text, "Test"),
  12.      new TypedValue((int)LispDataType.ListEnd),
  13.      new TypedValue((int)LispDataType.ListEnd)
  14.    }
  15.   );
  16.   var res = Application.Invoke(rb);
  17. }

Результат:

Команда: TESTINV1

"Name . Test"