明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 1031|回复: 10

[经验] 【原创】函数中的局部变量是如何实现的

[复制链接]
发表于 2024-8-8 14:35:26 | 显示全部楼层 |阅读模式
本帖最后由 baitang36 于 2024-8-8 15:29 编辑

一般定义函数是这样写的:  
(defun tt(v1 v2  /  a  b c) (princ a))
在函数的参数中,斜杠后面的是局部变量,它是如何实现的呢?
反编译一下,发现它调用了一个保留函数_al-bind-alist ,看字面意思是绑定一个列表。
什么是绑定呢?对应的应该有个解绑函数吧?
深入研究,还真的有解绑函数,它叫_unbind 只有一个参数,就是局部变量的个数。
绑定的意思是保存原来的符号值,解绑就是恢复原来的符号值。
这两个函数配合,可以随时绑定和解绑,也就是能自己控制一个符号是全局变量,还是局部变量。
请看试验代码:
  1. (load "c:/00/trf_9.fas")
  2. (tranf "_al-bind-alist")
  3. (tranf "_unbind")
  4. (defun t1 ()
  5.   (_al-bind-alist '(a b c))
  6.   (setq a "\n这里的a是局部变量")
  7.   (princ a)
  8.   (_unbind 3)
  9.   (princ a)
  10.   (princ)
  11.   (_al-bind-alist '(a))
  12.   (setq a "\n二次绑定试验")
  13.   (princ a)
  14.   (princ)
  15.   (_unbind 1)
  16.   (princ a)
  17.   (princ)
  18. )
  19. (setq a "\n这里的a是全局变量")
  20. (t1)

函数参数的传递方法和这个类似,是通过24号指令来绑定,在函数结束前用25号指令解绑。
_unbind函数必须和_al-bind-alist配对使用,否则会出现 错误: 出现异常: 0xC0000005 (访问冲突)
这种情况相当于访问并不存在的内存,因此报错。







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 5明经币 +5 收起 理由
tranque + 1 很给力!
hubeiwdlue + 1 赞一个!
p-3-ianlcc + 1 很给力!
tryhi + 1 赞一个!
自贡黄明儒 + 1 很给力!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2024-8-8 14:51:12 | 显示全部楼层
感谢大佬而分享
发表于 2024-8-8 15:10:09 | 显示全部楼层
在(_al-bind-alist '(a b c))和(_unbind 3)之间,可能还有处理办法,如果用户按了Esc呢?
 楼主| 发表于 2024-8-8 15:12:50 | 显示全部楼层
本帖最后由 baitang36 于 2024-8-8 15:14 编辑
自贡黄明儒 发表于 2024-8-8 15:10
在(_al-bind-alist '(a b c))和(_unbind 3)之间,可能还有处理办法,如果用户按了Esc呢?

如果中途退出函数,可能的后果是没有恢复原来的全局变量,符号的值是局部变量的值。
人为造成这种错误,故意不让它解绑,可能获取到真正的注册码。
发表于 2024-8-8 15:18:28 | 显示全部楼层
本帖最后由 tryhi 于 2024-8-8 15:24 编辑

试了一下_unbind函数也可以在外面用,但前面必须有个_al-bind-alist,也就是说有些需要运行在外面的代码块,可以用这个定义“块”级别的局部变量,不过调用_unbind风险感觉挺大的,一旦出错CAD就致命错误,而且vl-catch-all-apply都无法拦截

点评

_unbind相当于25号指令  发表于 2024-8-8 15:30
 楼主| 发表于 2024-8-8 15:32:27 | 显示全部楼层
tryhi 发表于 2024-8-8 15:18
试了一下_unbind函数也可以在外面用,但前面必须有个_al-bind-alist,也就是说有些需要运行在外面的代码块 ...

如果绑定的个数小于解绑的个数,那一定会崩。
发表于 2024-8-8 16:03:23 | 显示全部楼层
在fearch里面用就挺不错,弥补for这种循环代码块没有局部变量的缺陷
发表于 2024-8-8 18:03:37 | 显示全部楼层
本帖最后由 你有种再说一遍 于 2024-8-8 20:50 编辑


由于AutoLisp语言是global的,不是local的,所以就有把全局变量转为局部变量的骚操作.
其实大家更喜欢的是默认局部变量,然后要全局才声明,而局部变量由编译器自动计算生命周期,而不是自己填入函数后面的括号.
这就不得不补充CPU运行原理了,
每个函数运行时都会开辟栈帧,栈帧内变量其实不存在释放(删除资源表记录/置0),而是修改对齐栈指针(ESP或RSP寄存器)来结束函数.
而堆则会进行删除资源等操作.
也就是其实AutoLisp全是跑堆上面的...
那么如果要做一个编译器,就可以自行计算生命周期,然后把这个代码到局部函数的头尾了.
例如lispTolisp,然后vlide编译第二份lisp.
不过既然那么复杂,为什么不直接lispToArx/lispToCsharp呢.

 楼主| 发表于 2024-8-9 09:42:22 | 显示全部楼层
本帖最后由 baitang36 于 2024-8-9 09:44 编辑
你有种再说一遍 发表于 2024-8-8 18:03
由于AutoLisp语言是global的,不是local的,所以就有把全局变量转为局部变量的骚操作.
其实大家更喜欢的是 ...

全局变量在内存中就是个地址,好像找不到exe中的变量名。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 09:55 , Processed in 0.218880 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表