Grrr1337 发表于 2018-10-4 08:05:14

定义LISP函数

各位.NET开发人员,
我想问一下,是否可以通过C#/定义一个LISP函数。NET中,通过提供实际的LISP代码
我的意思是将LISP代码放在.NET代码中,然后编写它并动态定义它
基本上就像将其传递到VLIDE的控制台并定义它:
(defun C:test ( / str )
(if (setq str (getstring "\nType something: "))
    (alert str)
)
(princ)
)
第二个问题:如何再次通过.NET调用LISP函数本身
**** Hidden Message *****

gile 发表于 2018-10-4 08:40:52

Hi,您可以简单地这样做:使用Document.SendStringToExecute()方法在命令行中输入代码,然后使用Document.SendStringToExecute()方法调用LISP函数(该方法不同步运行,或者使用Application.Invoke()方法(该方法同步运行并允许获取LISP函数返回值)。定义LISP:[命令方法("LISPDEF")]。
公共静态空LispDefine()。
{。
var code="(defunc: test(/str ) " +。
"(if(setq str(getstring\"\n键入: \"))" +。
"(警报str)"+。
")" +。
"(princ)"+。
")";。
var doc=Application.DocumentManager.MdiActiveDocument;。
doc.SendStringToExecute(代码+"\n", false, false, false);。
}调用LISP:[命令方法("LISPCALL")]。
公共静态无效LispCall()。
{。
var args=new ResultBuffer(new TypeValue(1,"c: test"));。
Application.Invoke(args);。
}但是,IMO,您应该避免将来自. NET的LISP混合在一起,NET,大多数这样带来的问题比解决方案更多。

Grrr1337 发表于 2018-10-4 10:11:13

嗨,gile,(我一直在等你回答)
非常感谢!
我之所以提出这个问题,是因为目前我还没有足够的自信/舒适来投入其中。我已经学习了一点如何显示一个窗口窗体和收集输入,(你知道:Form > DCL)..
然而,在收集了输入之后,在ACAD开始代码执行操作的可怕部分(我发现现在用LISP更容易做到)。
所以这应该是有更多编码的部分,这意味着抛出许多不同的异常,不知道如何调试它们(因为我得到了令人不舒服的属性)。
但在这一点上我同意你的看法-
我的计划是慢慢钻研。NET,通过减少我通过LISP atm填补的空白。

gile 发表于 2018-10-4 11:13:44

LispFunction属性可能会引起一些兴趣,允许发送/返回列表和其他好东西
         
      // Note: you can return types bool, int, double, Point2d, Point3d, ObjectID, TypedValue,
      // ResultBuffer or null to lisp
      static public ResultBuffer lisp01(ResultBuffer pArgs)
      {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                if (pArgs != null)
                {
                  List inArray = new List(pArgs.AsArray());
                  return new ResultBuffer(inArray.ToArray());
                }
            }
            catch (System.Exception ex)
            {
                _AcAp.Application.ShowAlertDialog(
                  string.Format("\nError: {0}\nStackTrace: {1}", ex.Message, ex.StackTrace));
            }
            return null;
      }

Grrr1337 发表于 2018-10-4 11:18:59

如果问题与对话框有关,您可以使用. NET构建对话框,并通过LispFunction(即使用LispFunction属性装饰的方法)将其公开给LISP。如果我必须混合. NET和LISP,我宁愿这样做这是一个简单的示例,其中包含一个TextBox和一个NumericUpDown的简单对话框:The Dialog类将数据公开为属性:使用System.Windows.Forms;。

命名空间LispDialogSample。
{。
公共部分类对话框:窗体。
{。
公共对话框()。
{。
初始化组件();。

//可以在[设计]选项卡中设置以下属性。
btnOk.DialogResultDialogResult.OK。
btnCancel.DialogResultDialogResult.Cancel。
}。

公共字符串TextValue=>textBox1.Text;。

公共int NumericValue=>(int)numericUpDown1.Value;。
}。
}LispFunctions类定义了'GetDataFromDialog'LISP函数,该函数打开对话框以获取用户输入并将数据作为列表返回(如果取消则为nil):使用System.Windows.Forms;。

使用Autodesk.AutoCAD.DatabaseServices;。
使用Autodesk.AutoCAD.Runtime;。

使用AcAp=Autodesk.AutoCAD.ApplicationServices.Application;。

命名空间LispDialogSample。
{。
公共类LispFunctions。
{。

公共静态ResultBuffer GetDataFromDialog(ResultBuffer resbuf)。
{。
var dialog=new Dialog();。
var结果=AcAp.ShowModalDialog(对话框);。
如果(结果!=DialogResult.OK)。
返回null;。
返回新的ResultBuffer(。
新类型值((int)LispDataType.Text,dialog.TextValue),。
新的TypeValue((int)LispDataType.Int32,dialog.NumericValue));。
}。
}。
}。
在网络加载时,您可以在LISP例程中使用此函数:(if (setq data (getdatafromdialog))
(alert (strcat "Text: " (car data) "\nNumber: " (itoa (cadr data))))
(alert "Cancelled operation")
)编辑:Daniel更快...。

gile 发表于 2018-10-4 17:09:28


感谢nullptr,它看起来非常有趣-
_$ lisp01
#>
_$ (lisp01 5)
(5)
_$ (lisp01 1 2 3 4)
(1 2 3 4)
_$ (lisp01)
nil
_$ (lisp01 '("A" "B" "C" "D"))
("A" "B" "C" "D")
_$ (lisp01 '((00 01 02 03)(10 11 12 13)(20 21 22 23)(30 31 32 33)))
((0 1 2 3) (10 11.0 12.0 13.0) (20 21 22 23) (30 31 32 33))
_$ (lisp01 1 2 3 '(1 2 3) '(4 5 6))
(1 2 3 (1.0 2.0 3.0) (4.0 5.0 6.0))

不过,我不确定它的用途。当传递符号或符号列表时,它似乎也会抛出异常:(lisp01'abc)或(lisp01'(a b c))
顺便说一句,它让我想起了<strong>列表
现在我对LispFunction属性有了更多的了解。
事实上,我现在更喜欢你混合.NET和LISP的方式。不过,我很高兴你按照我最初的问题透露了另一种方法
尽管我在声明对话框类中的公共变量时出错-
公共字符串TextValue=>textBox1.Text
公共int-NumericValue=>(int)numericUpDown1.Value

Error        9        'LispDialogSample_Gile.Dialog.numericUpDown1' is a 'field' but is used like a 'type'
通过使用System.Windows.Forms将它们定义为该类内部的属性来解决此问题
名称空间LispDialogSample_Gile
{
公共部分类对话框:表单
{
公共字符串TextValue{get;}
公共整数数值{get;}
公共对话框()
{
初始化组件()
//可以在选项卡中设置以下属性。
btnOk。DialogResult=DialogResult.OK
btnCancel。DialogResult=DialogResult.Cancel
}
私有void btnOk_Click(对象发送者,事件参数e)
{
TextValue=textBox1.Text
NumericValue=(int)numericUpDown1.Value
}//btnOk_Click
}
}

从您的帖子中学到了很多东西..很抱歉我的回复太晚(我花了一些时间来消化)
如果你们不介意的话,会出现另外一个问题:
正如你们可能猜到的,我是一个lisp专家,使用DCL收集用户输入
但我决定切换的主要原因,除了所有花哨的控件事件和独特的表单设计外,是因为DCL似乎没有一些控件
我说的是datagridview控件,它将构建字符串[,]类型的数组,或者在LISP中我将其称为字符串矩阵列表
换句话说,用表提示用户(用DCL几乎不可能做到这一点)
所以我的问题是,如何将字符串[,]数组传递给ResultBuffer();到LispDataType枚举?(假设我最初从DGV的单元格值构造字符串[,])
很抱歉再次询问(我不想在.NET论坛部分发送与LISP相关的问题线程)。

gile 发表于 2018-10-5 00:08:25


另外,不要忘记Open DCL,我认为它有一个很好的网格控制。

estanima 发表于 2018-10-5 02:20:52

这是属性get语句的C#6(或更高版本)语法,您也可以这样写:公共字符串TextValue。
{。
获取{返回textBox1.Text;}。
}。
公共int NumericValue。
{。
获取{返回(int)numericUpDown1.Value;}。
}[/引用]。

Grrr1337 发表于 2018-10-5 02:47:10

由于AutoLISP只知道(链接)列表作为数据结构,因此您必须将2维数组转换为列表,通常是每个子列表代表一行的子列表列表。。
公共ResultBuffer Foo(ResultBuffer resbuf)。
{。
var数组=新字符串。
{。
{"a","b","c"},。
{"d","e","f"}。
};。

返回Array2dToList(数组);。
}。

私有ResultBuffer Array2dToList(字符串[,]数组)。
{。
var retVal=new ResultBuffer();。
为(int i=array.GetLowerBound(0); i。
{。
retVal.Add(新的TypeValue((int)LispDataType.ListBegin));。
for(int j=array.GetLowerBound(1); j。
{。
retVal.Add(新的TypeValue((int)LispDataType.Text,数组);。
}。
retVal.Add(新的TypeValue((int)LispDataType.ListEnd));。
}。
返回retVal;。
}。

gile 发表于 2018-10-5 13:18:07

我开始的时候也试过。潜入朋友,C#。一旦曲线结束,net比lisp更容易(对我来说)
页: [1] 2
查看完整版本: 定义LISP函数