当前位置:文档之家› AUTOLisp教程

AUTOLisp教程

AutoLISP教程(一)

AutoLISP 是 LISP 编程语言的一种特定实现方式,是 AutoCAD 的组成部分。借助 AutoLISP,可以用适合编写图形应用程序的强大的高级语言来编写宏程序和函数。AutoLISP 易于使用,并且非常灵活。

AutoLISP 参考是关于 AutoLISP 编程语言的权威指南。作为通用 LISP 语言的一个小子集,AutoLISP 严格遵循其语法和惯例,但又添加了许多针对 AutoCAD 的功能。有关 LISP 的书籍很多,有兴趣进一步学习 LISP 的用户不难找到合适的参考书。

向您推荐 Addison-Wesley 出版的两本书:Winston 和 Horn 撰写的《LISP》(第二版),Tony Hasemer 撰写的《Looking at LISP》。

基础

在 AutoCAD 的 sample 目录中提供了大量 AutoLISP 程序,包括本手册中的许多样例。许多 AutoLISP 程序也可以作为共享软件或从第三方开发商获取。AutoLISP 代码可以在命令行中输入,因此易于学习。一旦用户学会 AutoLISP,即可将其用于扩展 AutoCAD 命令。

在命令行中输入文本时,AutoCAD 将该文本与内部的可用命令名列表作比较,以解释该文本。如果输入的文本与列表中的某项相匹配,AutoCAD 执行该命令。当 AutoCAD 接收到 AutoLISP 代码时,它将该代码传递给 AutoLISP 解释器。AutoLISP 解释器的核心是计算器。该计算器读取一行代码,对它求值,然后返回一个结果。代码必须符合 AutoLISP 表达式的格式要求,它可以从文件中读取,也可以由用户从 AutoCAD 命令行中输入。

所有 AutoLISP 表达式的格式都如下所示:

(function arguments)

每个表达式都以一个左括号开始,由一个函数名和一个该函数的参数组成,并且每个参数都可以是一个表达式。表达式以右括号结束。每个表达式都返回一个可由外层表达式使用的值。如果没有外层表达式,则 AutoLISP 将该值返回给 AutoCAD 命令行。例如,如下代码调用了三个函数。

(fun1 (fun2 arguments)(fun3 arguments))

第一个函数 fun1 有两个参数,另两个函数 fun2 和 fun3 各有一个参数。函数 fun2 和 fun3 被函数 fun1
所包含,因此它们的返回值作为参数传递给 fun1。函数 fun1 由这两个参数计算函数值,并将该值返回给命令行。

如果在 AutoCAD 命令提示中输入 AutoLISP 表达式,AutoLISP 将计算该表达式并显示结果,然后重新显示命令提示。下例展示了 *(乘)函数的用法,该函数接受一个或多个实数作参数。

命令: (* 2 27)

54

因为此函数没有外层表达式,所以它将结果返回给命令行。

嵌套在其他表达式中的表达式将它们的结果返回给外层表达式。下例用 +(加)函数的结果作 *(乘)函数的一个参数。

命令: (* 2 (+ 5 10))

30

如果输入的闭(右)括号数量不对,AutoLISP 将显

示如下提示:

n>

其中,n 是一个整数,表明还有几层左括号尚未匹配。如果出现此提示,用户必须输入 n 个右括号后才能对表达式求值。

命令: (* 2 (+ 5 10

2> ) )

30

常见错误是忽略了文本字符串中的双引号 (")。在这种情况下,右括号被解释为字符串的一部分,而不会对 n 产生影响。要改正此错误,可按 ESC 键取消该函数,然后重新输入正确的表达式。

虽然可以在命令行中输入 AutoLISP 代码,但在测试和调试 AutoLISP 代码时,从文件中加载 AutoLISP
代码要比每次修改后都重新输入要简单得多。AutoLISP 代码通常保存在扩展名为 .lsp 或 .mnl 的 ASCII 文本文件中。但只要在调用 load 函数时提供完整的文件名,就可以从任何 ASCII 文本文件中加载 AutoLISP 代码。从文件或在命令行中输入的 AutoLISP 表达式的语法相同。

AutoLISP 变量的数据类型取决于分配给它的值的数据类型。除非给变量分配新值,否则该变量将一直保留原来的值。可以用 AutoLISP setq 函数为变量分配新值。

(setq variable_name1 value1 [variable_name2 value2 ...])

setq 函数将指定的值分配给指定的变量,并将该值作为函数结果返回。如果在命令提示中使用 setq,则 AutoCAD 将设置变量并显示该值。

命令: (setq val 3 abc 3.875)

3.875

命令: (setq layr "EXTERIOR-WALLS")

"EXTERIOR-WALLS"

命令:

每个变量都要占用一小块内存,因此应当重复使用变量名或在不再需要时将它们设置为 nil,是一种良好的编程习惯。将变量设置为 nil 会释放用于保存该变量值的内存。例如用户不再需要 val 变量,可以用如下表达式释放其值:

命令: (setq val nil)

nil

数字处理

AutoLISP 提供了如下处理整数和实数的函数:

+(加) abs gcd minusp
-(减) atan log rem
*(乘) cos logand sin
/(除) exp logior sqrt
~(按位非) expt lsh zerop
1+(增 1) fix max
1-(减 1) float min
关于每个数字处理函数的详细信息,请参见第十三章“AutoLISP 函数列表”。
除了在应用程序中执行复杂的数学计算以外,用户也可在日常使用 AutoCAD 时用数字处理函数来协助完成工作。例如要将一条直线按照长度为模数 *3.1415... 切分,而模数为 3,可在命令提示中使用 *(乘)函数。

命令: measure
选择测量对象:

<分段长度>/块(B): (* 3 Pi)

如果给数字处理函数的 number 参数分别提供整数或实数值,则包含该参数的算术函数将返回不同的值。如果所有的参数都是整数,则返回值也是整数。但如果参数中存在实数,则返回值是实数。如果要确保应用程序返回实数值,则必须保证至少有一个参数

是实数。

命令: (/ 12 5)
2
命令: (/ 12.0 5)

2.4

虽然 AutoLISP 在其内部使用 32 位整数,但在 AutoLISP 和 AutoCAD 之间传递的整数却被限制为 16 位,即用户不能把大于 +32767 或小于 -32768 的整数传递给 AutoCAD。如果用户需要使用超出此范围的整数,可用 float 函数将它转换为实数,因为实数传递使用的是 32 位的值。

命令: (setq 32bit (float (* 3 30000)))

90000.0


字符串处理

AutoLISP 提供了如下处理字符串值的函数:

strcase strlen wcmatch
strcat substr
下列函数用于在字符串值和数字值之间相互转换(详细信息请参见转换函数)。

angtof atof distof
angtos atoi itoa
ascii chr rtos
下列函数用于在命令行中显示字符串值(详细信息请参见显示控制)。

prin1 print
princ prompt


strcase 函数用于将字符串中的所有字母字符转换为大写或小写。它接受两个参数:一个是字符串;另一个是可选参数,用于指定所返回字符的大小写。如果忽略可选的第二个参数,或它被赋值为 nil,那么 strcase 返回字母被转换为大写的字符串。

命令: (strcase "This is a TEST.")

"THIS IS A TEST."

如果为第二个参数提供了非 nil 值,则返回字母被转换为小写的字符串。AutoLISP 提供了预定义的变量 T,以便在这种需要用非 nil 值作真/假开关的情况下使用。但用户不必非要使用 T,也可以使用任何非 nil 值,只要该值更适合用户的应用程序。

命令: (strcase "This is a TEST." T)

"this is a test."

strcat 函数用于将多个字符串组合成一个字符串值。这有利于将变量字符串放到常量字符串中。如下代码将变量设置为一个字符串值,然后用 strcat 将该字符串插入到另一字符串中间。

命令: (setq str "BIG") (setq bigstr (strcat "This is a " str " test."))

"This is a BIG test."

单个字符串值的长度最大为 132 个字符。通过用 strcat 函数连接字符串,可以创建长度没有限制的字符串。
如果变量 bigstr 被设置为上述字符串值,则可以用 strlen 函数计算该字符串中的字符个数(包括空格)。

命令: (strlen bigstr)

19

substr 用于返回某个字符串的一个子串。它有两个必要参数和一个可选参数。第一个参数是字符串。第二个参数是一个整数,用于指定子串中第一个字符的位置。如果提供了第三个参数,则它指定子串中包括的字符数;如果未提供第三个参数,substr 将返回由指定的开始字符及其后的所有字符组成的字符串。
用户可以用 substr 函数将三个字母的扩展名从文件名中除去。首先,将某个变量设置为该文件名。(根据应用程序的不同,用户通常可以通过查询系统变量或读取用

户输入来达到此目的。)

命令: (setq filnam "bigfile.txt")

"bigfile.txt"

然后,用户需要获取一个字符串,该字符串应该包括除最后四个字符(句点和三个字母的扩展名)以外的所有字符。可以用 strlen 获取文件名字符串的长度,并从该值中减去四。然后用 substr 来指定子串的第一个字符及其长度。

命令: (setq newlen (- (strlen filnam) 4))
7
命令: (substr filnam 1 newlen)

"bigfile"

如果应用程序中不需要使用 newlen 的值,可将两行代码合并为一行:

命令: (substr filnam 1 (- (strlen filnam) 4))

"bigfile"

等量和条件

AutoLISP 中既包括验证等式的函数,也包括条件分支和循环函数。等式和条件函数包括:

=(等于) and or
/=(不等于) Boole repeat
<(小于) cond while
<=(小于或等于) eq
>(大于) equal
>=(大于或等于) if

表处理

AutoLISP 提供了如下处理表的函数:

append foreach listp reverse
assoc last mapcar subst
car and cdr length member
cons list nth
本节提供了 append、assoc、car、cons、list、nth 和 subst 函数的样例。

表提供了保存大量相关值的一种有效方法。一些 AutoLISP 函数为设计二维和三维图形应用程序提供了基本工具,这些函数以表的形式返回点值。
list 函数提供了将相关项组合成表的一种简单方法。这些相关项的数据类型可以不同。如下代码将三个相关的项组合为一个表。

命令: (setq lst1 (list 1.0 "One" 1))

(1.0 "One" 1)

nth 函数用于从表中检索指定序号的项。nth 函数接受两个参数。第一个参数是整数,指定项的序号。0
指定表中的第一项,1 指定第二项,依此类推。第二个参数是表本身。如下代码返回表 lst1 中的第二项。

命令: (nth 1 lst1)

"One"

car 和 cdr 函数提供了从表中读取项的另一种途径。关于使用 car 和 cdr 的样例,请参见点表。
有三个函数可对现有的表进行修改。append 函数在表的末尾添加新项,并返回新表;cons 函数在表的开始添加新项,并返回新表;subst 函数用新项替换找到的每一个旧项,然后返回新表。这三个函数不修改原来的表,而是返回修改后的表。要修改原来的表,必须用新表显式地替换原来的表。

append 函数可以接受任意数量的表,并将它们当作一个表来处理。因此,此函数的所有参数都必须是表。如下代码将另一个“One”添加到表 lst1 中。注意 quote(或 ')函数的用法,此函数是将字符串“One
”转换成表的简便方法。

命令: (setq lst2 (append lst1 '("One")))

(1.0 "One" 1 "One")

cons 函数用于将单个元素与表组合。用 cons 函数可以将另一个字符串“One”

添加到这个新表 lst2
的开始部分。

命令: (setq lst3 (cons "One" lst2 ))

("One" 1.0 "One" 1 "One")

substr 函数可以用新项替换表中所有出现的某个项。如下代码将用字符串“one”替换表中所有的字符串“One”。

命令: (setq lst4 (subst "one" "One" lst3))

("one" 1.0 "one" 1 "one")

符号和函数处理

AutoLISP 提供了如下处理符号和变量的函数:

atom not quote type
atoms-family null set
boundp numberp setq

AutoLISP 提供了如下处理一组或多组函数的函数:

apply eval progn untrace
defun lambda trace
本节提供了 defun 函数的样例。

借助 AutoLISP,用户可定义自己的函数。一旦定义了这些函数,即可象使用标准函数一样在命令行或 AutoLISP 表达式中使用它们。用户也可以创建自己的 AutoCAD 命令,因为命令只是一种特殊类型的函数。
defun 函数(请参见第十三章“AutoLISP 函数列表”中的 defun)可将一组表达式组合到一个函数或命令中。此函数至少需要三个参数。第一个参数是要定义的函数的名称(符号名)。第二个参数是参数表(由该函数使用的参数和局部符号组成的表),参数表可以为 nil 或空表 ( )。关于参数表的详细信息,请参见带参数的函数。如果提供了局部符号,则要用斜杠 ( / ) 将它们与参数分隔开。关于局部符号的详细信息,请参见函数中的局部符号。在这些参数之后是组成函数的表达式,函数定义中至少要包括一个表达式。

(defun symbol_name ( args / local_symbols )
expressions
)

如下代码定义了一个简单的函数,该函数不接受任何参数,只在命令行中显示一条信息。注意:参数表是空表 ( () )。

命令: (defun DONE ( ) (prompt "\nbye! "))

DONE

现在,DONE 函数已经定义完毕,可以象使用其他函数一样使用它。因为 DONE 函数只是在命令行中另起一行打印信息 bye!,所以可以按如下方式使用该函数:

命令: (prompt "The value is 127. ")(DONE)(princ)
The value is 127

bye!

不接受任何参数的函数看起来用处不大。但可以用这种函数来查询某个系统变量或条件的状态,并返回表明该状态的值。
注意 请不要在其他地方使用 S:: 函数名前缀,此前缀仅用于特殊函数 S::STARTUP。

错误处理

AutoLISP 提供了如下错误处理函数:

alert *error* exit quit

AutoLISP 提供了处理用户(或程序)错误的方法。适当地使用 *error* 函数可确保 AutoCAD 在错误发生后返回特定的状态。通过这个可自定义的函数,用户可以测试错误条件并向用户返回适当的信息。
如果 AutoLISP 在计算过程中遇到错误,它将按如下格式显示一条信息:

错误: text

在此信息中,text 描述

了发生的错误。如果用户自定义了 *error* 函数(非 nil), AutoLISP 执行该函数(text 作为唯一的参数传递给它)时,将不显示上述信息。如果沿用系统的 *error* 函数(或为 nil),AutoLISP 将中断程序的执行,并显示最多 100 层深的函数调用过程。调试程序时最好使此错误处理函数保持系统的原始定义。
最后一个错误的代码保存在 AutoCAD 的系统变量 ERRNO 中,可以用 getvar 函数检索该代码。

在自定义的 *error* 函数描述中,应该保存 *error* 的当前内容,这样可在退出应用程序时恢复原来的错误处理。当存在错误条件时,AutoCAD 调用当前定义的 *error* 函数并传给它一个参数,该参数是一个描述错误性质的文本字符串。*error* 函数应该设计为在 ESC(取消)或 exit 函数调用后静默退出。实现此功能的标准方法是在自定义的错误处理程序中包括如下语句:

(if
(or
(/= msg "Function cancelled")
(= msg "quit / exit abort")
)
(princ)
(princ (strcat "\nError: " msg))
)

此代码检查传给它的错误信息,并确保将错误的性质通知用户。如果用户在错误处理程序运行时取消了该程序,则此代码不返回任何内容。同样,如果在代码中处理了错误条件并调用了 exit 函数,也不会返回任何内容。它假定程序中已经用打印语句解释了错误的性质。如果不需要在错误处理程序结束时显示返回值,请在该程序最后调用 princ 函数。
如果要调用 UNDO 函数一步放弃例程的运行结果,则必须提供带条件判断的 UNDO 调用,使得它仅在例程正常退出时被调用。事实上,用户可能需要 AutoCAD 放弃所有的操作。程序可以用 UNDOCTL 和 UNDOMARKS 系统变量来决定如何(或是否)调用 UNDO。

关于错误处理例程的主要问题是:它们本身也是普通的 AutoLISP 函数,可以被用户取消。因此应该使错误处理例程尽可能简短,并使其运行尽可能快,这样在调用该程序时,它完全执行的可能性将大大增加。
许多 ARX 定义的命令都拥有自己的函数或系统变量,可提供错误信息。请参见第十四章“访问外部定义命令和系统变量”。
也可以显示警告对话框来告诉用户发生的错误条件。警告对话框是包含程序所提供信息的小对话框。要显示警告对话框,可调用 alert 函数。

如下调用 alert 将显示一个警告对话框。

(alert "File not found")







相关主题
文本预览
相关文档 最新文档