在 AutoCAD 2000 或更高版本中有一个新的 AutoLISP 解释器。这个新版本的 AutoLISP 纠正了旧版本中存在的某些问题,并修改了某些函数的执行方式。
因为可以在 AutoCAD 中同时打开多个图形文档,所以 AutoCAD 处理自定义文件(例如 acad.lsp)的方式必须改变。这些处理方式的改变可控制打开新图形时 AutoCAD 加载哪些自定义文件。有关使用自定义文件的详情,请参见 Customization Guide 中的“Automatically Load and Execute AutoLISP Routines”。
符号保护
当 Visual LISP 运行时,保护的符号(例如 T)被真正保护,如果试图修改这些符号将出现错误信息。关于符号保护如何工作的信息,请参见 Visual LISP Developer's Guide 中“Using the AutoLISP Language”的“AutoLISP Basics”。
函数不再被内部定义为表
函数不再被内部定义为表。如果有依赖函数表结构的代码,则可以使用 DEFUN-Q、DEFUN-Q-LIST-SET 和 DEFUN-Q-LIST-REF 函数以保持后向兼容性。关于使用这些函数的信息,请参见联机 AutoLISP Reference。
AutoLISP 错误信息已更改
在 AutoCAD 中许多 AutoLISP 错误信息文本已更改。这可能会影响依赖错误字符串内容的任何 AutoLISP 代码。
整数溢出可以被转换为实数
AutoLISP 的早期版本处理整数溢出(大于 2147483647 的正数,小于 -2147483648 的负数)的方法是返回负数或生成随机数。在 AutoCAD 2000 和更高版本中,AutoLISP 处理整数溢出的方式有所不同。如果输入的数大于最大允许整数,则 AutoLISP 将此整数转换为实数。但是,如果对两个有效的整数执行数学运算,并且结果大于最大允许整数,则结果数字无效。关于 AutoLISP 如何处理整数溢出的详细信息,请参见 Visual LISP Developer's Guide 第八章中的“AutoLISP Data Types”。
最小整数稍有不同
AutoLISP 允许的最小整数值现在为 -2147483647。在 AutoCAD R14 中,最小整数值是 -2147483648。
符号表名称中保留大小写
在 AutoCAD R14 和早期版本中,符号表名称条目在创建时被自动转换为大写。在 AutoCAD 2000 或更新版本中,AutoLISP 保留符号表名称的大小写。在现有的应用程序中,如果使用区分大小写的符号表名称字符串比较,可能会导致冲突。可能需要修改应用程序,使字符串不区分大小写。
如果将函数作为参数传递给 ObjectARX defun'd 函数,将返回错误
AutoLISP 始终不允许将函数作为参数传递给 ObjectARX defun'd 函数,但以前此操作并不返回错误信息。在 AutoCAD 2000 或更高版本中,如果将函数作为参数传递给 ObjectARX defun'd 函数,AutoLISP 将显示以下错误信息:
*** ERROR:doesn't fit in resbuf:# 在特殊格式的运算符位置不允许使用表达式 某些 AutoLISP 函数被认为是“特殊的格式”,因为它们计算参数的方式与大多数 AutoLISP 函数调用不同。通?:?数计算它的所有参数。特殊的格式(例如 IF、AND、COND 和 SETQ)不计算所有参数,或只在某些条件下才计算某些参数。在 AutoLISP 早期版本中,将计算到特殊格式的表达式放在运算符位置是合法的。在 AutoCAD 2000 和更高版本中,不支持这种做法。例如,在 AutoCAD R14 中下列函数调用的结果: 命令:((if t if) nil (princ 1) (princ 2)) 22 在 AutoCAD 2000 或更高版本中使用相同的函数调用: 命令:((if t if) nil (princ 1) (princ 2)) 12; 错误: 无法应用特殊格式: IF 运算符位置的计算顺序不同 AutoLISP 的早期版本先计算表达式中的运算符位置,然后从左到右计算参数。在 AutoCAD 2000 和更高版本中,AutoLISP 先从左到右计算参数,然后再计算运算符。 不允许 LAMBDA 主体为空 在 AutoCAD 2000 和更高版本中,主体为空的 lambda 语句将导致语法错误。这种结构在 AutoCAD R14 中可以使用。这种 lambda 主体可能出现在 LAMBDA、DEFUN、DEFUN-Q 和表函数表达式中。例如,下列语句将导致错误: (lambda (a)) (setq func '(a)) (func) 下列表达式是有效的: (lambda (a) nil) (setq func '((a) nil)) (func) 在多种访问模式中同时打开文件的处理 单个文件在不同的访问模式下同时打开的处理已经被纠正。在 AutoLISP 的早期版本中,打开单个文件并同时执行读、写和附加到文件将产生可重复但不标准的结果。在一个文件上的操作影响其他文件上的下一个操作。在 AutoCAD 2000 和更高版本中,下一个读、写或附加操作的位置被定位在每个打开的文件上,并在程序员的控制之下。例如,以下函数在 R14 与 AutoCAD 2000 和更高版本中执行的结果不同: (defun file-handle () (setq write-ptr (open "test.txt" "w") append-ptr (open "test.txt" "a") read-ptr (open "test.txt" "r")) ;; 用写模式写五行 (repeat 5 (write-line "write-mode lines" write-ptr)) ;; 用附加模式写五行 (repeat 5 (write-line "append-mode lines" append-ptr)) ;; 从文件开头读文件内容 (while (print (read-line read-ptr))) (close write-ptr) (close append-ptr) (close read-ptr) (princ) ) 在 AutoCAD R14 中,函数执行结果为一个包含十行文字的文本文件(五行包含字符串“write-mode lines”,五行包含“append-mode lines”)。在 AutoCAD 2000 和更高版本中,得到的文件只包含五行“append-mode lines”,因为用于添加模式的文件指针未被写操作重置。 结果溢出的 EXPT 返回不同的值 在 AutoCAD R14 中,EXPT 表达式计算出的值如果超过 AutoLISP 双精度浮点范围将返回 0。在 AutoCAD 2000 和更高版本中,同一个表达式将返回“1.#INF”。 在 LISPINIT=1 的 SDI 中,在后续的图形中不加载 ACAD.LSP 和 MNL 文件 在 SDI 模式下运行并将 LISPINIT 系统变量设置为 1 时,acad.lsp 文件只加载到启动文档中,而不是加载到所有在 AutoCAD 任务中后续打开的图形中。为确保将 acad.lsp 加载到所有新文档中,请将 ACADLSPASDOC 系统变量设置为 1。 OSNAP 的新默认设置可能导致应用程序失败 OSMODE 系统变量的默认设置在 AutoCAD 2000 中已改变,可能会影响采用旧默认设置的应用程序。在 AutoCAD R14 中,OSMODE 的默认值为 0,意味着对象捕捉是关闭的。在 AutoCAD 2000 和更高版本中,OSMODE 的默认设置为 4133,意味着对象捕捉点是打开的。如果这对应用程序有影响,请更改代码以保存当前的 OSMODE 设置,并根据需要设置 OSMODE,然后在退出之前恢复原来的 OSMODE 值。建议将此编程实践经验用于所有处理图形对象的 AutoCAD 应用程序。 长度超过 4K 字符的打印序列显示乱码 打印列表包含的字符超过 4K 时,在缓存区大小固定的情况下将导致循环溢出,联机查看时,输出显示乱码。解决办法是修订 LISP 应用程序的代码,使一次打印输出的信息不超过 4K。即,将打印输出分成多个 print 语句。 ENTMAKE 中的标注箭头信息的转换 在 AutoCAD R14 中,标注箭头由名称控制,dimblk、dimblk1 和 dimblk2 的名称分别用组码 5、6 和 7 表示。在 AutoCAD 2000 和更高版本中,箭头由 objectID 控制。dimblk、dimblk1 和 dimblk2 的 objectID 用组码 342、343 和 344 表示。出于兼容性考虑,AutoCAD 2000 和更高版本可识别 5、6、7 组码,但是如果图形中没有用 5、6、7 代码命名的箭头块,该设置被忽略。例如,如果 R14 代码使用 entmake 来创建包含箭头“DOT”的标注,若图形中已存在名为“_Dot”的块,则继续使用“DOT”。如果在发出 entmake 时不存在 _Dot 块,entmake 仍会成功,但是箭头设置失败,并且用默认“_CloseFilled”箭头创建标注。解决方法是:修改程序,使之在 entmake 中指定箭头之前始终强制显示内置箭头。例如,使用 DIMBLK 系统变量将该箭头设置为当前箭头。这将强制创建块。 得到返回结果之前不显示打印信息 在 AutoCAD R14 中,每个 AutoLISP 打印函数(例如 print、princ)都自动回显到 AutoCAD 命令行并立即可见。在 AutoCAD 2000 和更高版本中,显示驱动程序将缓存打印信息,直到得到返回结果(/n 或 /r)。结果,函数完成之前可能不显示信息。例如,在 R14 中,下列代码一遇到 princ 就发出信息“Wait. Program is busy...”。 (defun test() (setq count 0) (princ "\nWait.Program is busy...") (while (< count 100000) (setq count (1+ count))) (princ "\nCounted: ") (princ count) (princ) ) 在 AutoCAD 2000 和更高版本中,不显示“Program is busy”的信息,直到在 while 循环后面遇到下一个 \n(已开始等待)。为确保立即显示信息,请在打印函数调用的结尾添加 \n 或 \r。例如: (princ "\nWait. Program is busy...\n") 表若以整数开头,在被传递到外部函数时可能被错误地解释为 DXF 代码 在将以整数值开头的表传递给外部定义的函数时,AutoLISP 可能错误的将整数解释为 DXF 组码。例如,在 AutoCAD R14 中可以调用在 acrender.arx 中定义的 c:light 函数,但是在 AutoCAD 2000 和更高版本中,此调用则会发生错误: (c:light "nd" "plan" 1.0 '(10 10 10) '(6 8 0)) 错误信息显示为: Render API error:Expecting a 3d point, but got an unknown type: ???. 解决办法是指定实数而不是整数。例如,以下调用可以正确运行: (c:light "nd" "plan" 1.0 '(10.0 10.0 10.0) '(6.0 8.0 0.0)) 修改填充比例不会触发填充图案重新计算 在 AutoCAD 2000 和更高版本中,修改填充对象的比例因子不会强制填充对象重新计算填充图形。要强制进行另一次计算,请使用 entmod 更改填充图案两次:第一次进行更改,第二次将其恢复。 减小了 GET_TILE 函数处理的最大字符串长度 用 get_tile 从 DCL 文件获得的字符串的上限在 AutoCAD R14 中为 2084 个字符,在 AutoCAD 2000 和更高版本中减少为 254 个字符。 AutoCAD R14 的 Visual LISP 兼容性 现在,Visual LISP 交互式开发环境 (IDE) 已经与 AutoCAD 集成,不再是单独的组件。 ActiveX 函数的新数据类型 现在,调用 ActiveX 方法的函数调用要求将参数定义为变量数据。ActiveX 函数也返回变量值。此更改表示所有使用 AutoCAD R14 的 VisualLISP 开发的 AutoLISP ActiveX 代码必须修改。关于在 AutoCAD 2000 和更高版本中使用 ActiveX 方法的详细信息,请参见 Visual LISP Developer's Guide 第六章“Working with ActiveX”。 现在,必须显式加载 ActiveX、反应器和 Visual LISP 扩展函数 默认情况下,启动 AutoCAD 时,不加载 AutoLISP ActiveX、反应器和 Visual LISP 扩展 (vlax-*) 函数。这种变化明显缩短了 AutoCAD 的启动时间,但是这意味着必须显式加载这些函数,以便在 AutoLISP 应用程序中使用。使用 (vl-load-com) 加载 ActiveX、反应器和 Visual LISP 扩展函数。 注意:在发出 vl-load-com 之前,不能从 Visual LISP 获得 AutoLISP ActiveX 函数的帮助。如果运行 vl-load-com 之前发出 ActiveX 函数的帮助请求,Visual LISP 将在 VLISP 控制台窗口中显示“error:no function definition:get-ACAD-itl error”。 不再支持用 Visual LISP 创建 ObjectARX 模块 在 AutoCAD R14 中,使用 Visual LISP 可以从 VLISP 应用程序创建可执行的 ObjectARX 模块。此版本中不再支持此操作。新的应用程序类型 VLX 替换了以前通过 ObjectARX 实现的功能。关于编译 VLX 的信息,请参见 Visual LISP Developer's Guide 第四章中的“Building Applications”。 现在,VLR-REACTORS 函数返回元素为表的表 现在,使用 VLR-REACTORS 函数可以指定列出多个反应器类型;这将返回一个元素为表的表,每个反应器类型为一个表。 Visual LISP 错误信息已修改 在 AutoCAD 2000 和更高版本中许多 Visual LISP 错误信息的文本已更改。这可能会影响用 AutoCAD R14 的 Visual LISP 开发的、以错误字符串内容为依据的任何代码。 VL-VBALOAD 返回 Nil,而不是文件名 在 AutoCAD R14 中,VL-VBALOAD 函数成功完成时返回加载的 DVB 文件的名称。在 AutoCAD 2000 和更高版本中,成功执行的 VL-VBALOAD 返回 nil。 不能访问 LDATA VLAX-LDATA-PUT 和 VLAX-LDATA-GET 函数调用图形中应用程序特有的 LISP 数据。AutoCAD 2000 和更高版本不能读取或识别由 AutoCAD R14 的 Visual LISP 创建的 ObjectARX 应用程序所创建的 LDATA