Visual LISP, AutoLISP and General Customization

Visual LISP, AutoLISP and General Customization

Reply
Distinguished Contributor
dbrblg
Posts: 314
Registered: ‎10-10-2007
Message 1 of 21 (409 Views)

Variable Scope

409 Views, 20 Replies
09-27-2012 06:38 AM

I've had a quick look around the forums but cannot find anything on variable scope......

 

How do I define a global variable where I can access from two different lisp functions?

 

For example, something along the lines of:

(vl-load-com)

[var x]

(defun func2 ()
  (setq x "ABC")
  (princ)
)

(defun func1 ()
  (setq x "DEF")
  (princ)
)

 

Thanks

 

 

*Expert Elite*
Kent1Cooper
Posts: 5,500
Registered: ‎09-13-2004
Message 2 of 21 (405 Views)

Re: Variable Scope

09-27-2012 07:05 AM in reply to: dbrblg

dbrblg wrote:

.....

How do I define a global variable where I can access from two different lisp functions?

 

For example, something along the lines of:

....
(defun func2 ()
  (setq x "ABC")
  (princ)
)

(defun func1 ()
  (setq x "DEF")
  (princ)
)

....


If you want to be able to set or change the variable x from within more than one function, and have either function replace any value set into that variable by the other, then what you have will work, not listing x as a localized variable within either one.  If you want each of the functions to have its own value in x without affecting its value for the other function, then it can't be global -- you would need to either localize it within each function:
 
(defun func1 (/ x)

....

 

[which would mean each function would need to make any use of x before it finishes], or it would need to have a different name in each function, such as x1 and x2.

 

Or am I misunderstanding what you're trying to do?

Kent Cooper
*Expert Elite*
M_Hensley
Posts: 1,712
Registered: ‎12-11-2003
Message 3 of 21 (384 Views)

Re: Variable Scope

09-28-2012 04:00 AM in reply to: dbrblg

You could save data in the registry and access it later from anther lisp by using SETENV and GETENV functions.

Distinguished Contributor
dbrblg
Posts: 314
Registered: ‎10-10-2007
Message 4 of 21 (381 Views)

Re: Variable Scope

09-28-2012 04:08 AM in reply to: dbrblg

Thanks for your suggestions. 

 

I'm giving up with lisp for the time being...may eventually get back to it when I have found some patience.

 

I cannot believe lisp still exists in Autocad:smileyfrustrated:

*Expert Elite*
Kent1Cooper
Posts: 5,500
Registered: ‎09-13-2004
Message 5 of 21 (366 Views)

Re: Variable Scope

09-28-2012 06:17 AM in reply to: dbrblg

dbrblg wrote:

.... 

I'm giving up with lisp for the time being....


Don't give up yet.  I admit it's not clear to me what you mean by the phrase "variable scope" [for example, is "variable" there a noun or an adjective?].  If you can describe in more detail what you want to accomplish, or how you want to use the variable(s), there may well be something here already, or someone may come up with an easy solution, or it may be appropriate to something like [in the case of your sample settings] the USERS1-through-USERS5 System Variables, or something.

Kent Cooper
Distinguished Contributor
dbrblg
Posts: 314
Registered: ‎10-10-2007
Message 6 of 21 (363 Views)

Re: Variable Scope

09-28-2012 06:38 AM in reply to: dbrblg

Hi Kent,

 

I'm trying to do something really quite simple....well, or so I thought anyway :smileysurprised:

 

With reference to my variable scope, I suspect I used a generic name to describe what I want.  It is a little ambiguous but I also suspect the terminology in lisp may be different from that of other languages.  

 

Basically what I am trying to achieve is to switch on certain points when a certain command is activated and then return them to what they were before when the command ends.

 

For example I have this:

(vl-load-com)

(defun c:StartReactor ()
  (or *Reactor_Command*
      (setq *Reactor_Command*
	     (vlr-lisp-reactor
	       "My command reactor "
	       '((:vlr-lispWillStart . Callback:LispWillStart)
		 (:vlr-lispEnded . Callback:LispEnded)
		)
	     )
      )
  )
  (prompt "\n  >>  Command reactor loaded ")
  (princ)
)

(defun Callback:LispWillStart (rea cmd)
;;;  (alert (strcat "Lisp started: " (car cmd)))
  (if (eq (car cmd) "(C:AEFOOTPRINT)")
    (progn
      (prompt (car cmd))
      (setq pointMode (getvar 'PDMODE))
      (prompt (strcat "\n pointMode Variable: " pointMode "\n PDMODE Variable: " (itoa(getvar 'PDMODE))))
      (setvar "PDMODE" 99)
      (prompt (strcat "\n PDMODE Variable: " (itoa(getvar 'PDMODE))))
    )
  )
  (princ)
)

(defun Callback:LispEnded (rea cmd)
;;;  (alert "Lisp ended")
  (if (/= pointMode nil)
    (progn
      (prompt (strcat "\n PDMODE Variable: " (pointMode)))
      (setvar 'PDMODE pointMode)
    )
(prompt (strcat "\n pointMode Variable is nil"))
  )
  (princ)
)

  (defun c:StopReactor ()
    (if	*Reactor_Command*
      (progn
	(vlr-remove *Reactor_Command*)
	(setq *Reactor_Command* nil)
      )
    )
    (prompt "\n  >>  Command reactor stopped ")
    (princ)
  )


(defun *error* (x) (vl-bt))

 As you can see there are a lot of prompts and alerts in there.  The debugger in Autocad is primitive to say the least (or it's me not grasping it fully) and i'm finding it a nightmare to debug properly.

 

The idea with the variable is there is one (called pointMode) which is shared between the LispWillStart and LispEnded functions which holds the state of PDMODE before it is changed and then allows it to be restored.

 

Thats the idea anyway.  I'm getting so many errors it's quite hard to describe where to start, hence I thought a break would be in order. 

 

Make of this what you will :smileyhappy: it's not particuarly 'tidy' or efficient shall we say....but then again, lisp is not my first language, but you may have guessed that!!

 

 

*Expert Elite*
Kent1Cooper
Posts: 5,500
Registered: ‎09-13-2004
Message 7 of 21 (354 Views)

Re: Variable Scope

09-28-2012 10:09 AM in reply to: dbrblg

dbrblg wrote:

.... what I am trying to achieve is to switch on certain points when a certain command is activated and then return them to what they were before when the command ends.

 

For example I have this:

....
      (setq pointMode (getvar 'PDMODE))
      (prompt (strcat "\n pointMode Variable: " pointMode "\n PDMODE Variable: " (itoa(getvar 'PDMODE))))
      (setvar "PDMODE" 99)
      (prompt (strcat "\n PDMODE Variable: " (itoa(getvar 'PDMODE))))
....
 
....
  (if (/= pointMode nil)
    (progn
      (prompt (strcat "\n PDMODE Variable: " (pointMode)))
      (setvar 'PDMODE pointMode)
    )
(prompt (strcat "\n pointMode Variable is nil"))
....

....The idea with the variable is there is one (called pointMode) which is shared between the LispWillStart and LispEnded functions which holds the state of PDMODE before it is changed and then allows it to be restored.

....


I haven't worked with reactors, but I notice a couple of things....

 

The pointMode variable will hold an integer, so you're going to need to convert that to a string to include it in a prompt.  After setting it to match PDMODE, you have a prompt that is telling the values of both, which will be the same.  And after setting PDMODE to 99, you're digging the value out of that, when you already know that's what it is.  Maybe something like this in place of the parts quoted above.

 

....
      (setq pointMode (getvar 'PDMODE))
      (prompt

        (strcat

          "\nCurrent PDMODE System Variable, saved in pointMode Variable: "

          (itoa pointMode)

          ".\nSetting PDMODE to 99."

        ); strcat

      ); prompt
      (setvar "PDMODE" 99)
....
 
....
  (if pointMode ; [easier than checking whether it's not equal to nil]
    (progn ; then
      (prompt (strcat "\nResetting PDMODE Variable to " (itoa pointMode)))
      (setvar 'PDMODE pointMode)
    ); progn
    (prompt "\n pointMode Variable is nil"); else [without unneeded (strcat)]

  ); if
....

Kent Cooper
Distinguished Mentor
Moshe-A
Posts: 745
Registered: ‎09-14-2003
Message 8 of 21 (338 Views)

Re: Variable Scope

09-28-2012 02:50 PM in reply to: dbrblg

Hi,

 

from my experience (of many years) there is no problem with global (or local variables) in AutoLISP

and i know some other languages that i can compare to. the rules are the same.

 

here is a fix i made for you especially look at (lprompt) functon which let to prompt any message

without the need to convert int/real to string.

 

Moshe

 

 

(defun lprompt (args / a)
 (foreach a args (princ a))
)


(vl-load-com)
(setq LISP-REACTOR-DATA "My command reactor")

(defun c:StartReactor ()
  (or *Reactor_Command*
      (setq *Reactor_Command*
	     (vlr-lisp-reactor
	       LISP-REACTOR-DATA
	       '((:vlr-lispWillStart . Callback:LispWillStart)
		 (:vlr-lispEnded     . Callback:LispEnded    )
		)
	     )
      )
  )
  
  (prompt "\n>>Command Reactor is enabled now.")
  (princ)
)

(defun Callback:LispWillStart (rea cmd)
;;;  (alert (strcat "Lisp started: " (car cmd)))
  (if (and (eq (vlr-data rea) LISP-REACTOR-DATA)
           (eq (car cmd) "(C:AEFOOTPRINT)")
      )
    (progn
      (lprompt (list "\n" (car cmd) "\n"))
      (setq pointMode (getvar 'PDMODE))
      (lprompt (list "start: pointMode Variable: " pointMode "\nstart: PDMODE Variable: " (getvar 'PDMODE) "\n"))
      (setvar 'PDMODE 99)
      (lprompt (list "start: PDMODE Variable: " (getvar 'PDMODE) "\n"))
    )
  )

  (princ)
)

(defun Callback:LispEnded (rea cmd)
;;;  (alert "Lisp ended")
  (if (and (eq (vlr-data rea) LISP-REACTOR-DATA)
	   (/= pointMode nil)
      )
   (progn
    (lprompt (list "ended: PDMODE Variable: " pointMode "\n"))
    (setvar 'PDMODE pointMode)
   )
   (prompt "\nended: pointMode Variable is nil.\n")
  )

  (princ)
)

(defun c:StopReactor ()
 (if *Reactor_Command*
  (progn
   (vlr-remove *Reactor_Command*)
   (setq *Reactor_Command* nil)
  )
 )
  
 (prompt "\n>>Command Reactor is Disabled now")
  
 (princ)
)


(defun C:AEFOOTPRINT ()
 ; only invokes (Callback:LispWillStart)
 (princ)
)

 

*Expert Elite*
scot-65
Posts: 2,175
Registered: ‎12-11-2003
Message 9 of 21 (335 Views)

Re: Variable Scope

09-28-2012 03:11 PM in reply to: dbrblg

dbrblg wrote:

How do I define a global variable where I can access from two different lisp functions? 


Global variables, for current session (until AutoCAD is closed), I refer to as "Gremlins".

I have a few of these written in several of my programs.

The structure I use to name this variable is "USER_xxx", where "xxx" is the routine name.

 

To create this Gremlin, do not declare the variable in the defun section, as you showed.

(defun c:MyABC ( / a b c)

 (setq a 1)

 (setq USER_MyABC "True")

 (princ)

)

 

USER_MyABC can now be seen by other programs, however "a" cannot.

 

It would be wise to declare this global variable outside the realm of the programs that access this.

Suggest declaring this inside any interface file (LSP, MNL, etc.), or in S::smileyfrustrated:TARTUP itself.

Suggest having long names with underscore(s), in case other third-party programs happen

to employ the same variable name as his gremlin. Yes, it has happened to me early on when

I inherited our menu system with these known bugs.

Suggest inside the program that will reference this variable to do a check first, then apply

a default value if not found: (if (not USER_MyABC) (setq USER_MyABC "True")).

 

Where SDI=0, and you switch drawings, can the next drawing see USER_MyABC?

I do not know this answer. But to be safe, you can use the SETCFG/GETCFG, and

VL-REGISTRY-READ/VL-REGISTRY-WRITE methods to access this across drawings.

 

Hope this helps.

 

???

 

Scot-65
Dyslexia is a permanent physical disability that cannot be seen.
Introverts is proof that there is indeed intelligent life on this planet.
Distinguished Mentor
Moshe-A
Posts: 745
Registered: ‎09-14-2003
Message 10 of 21 (332 Views)

Re: Variable Scope

09-28-2012 03:33 PM in reply to: scot-65

Hi Scot-65,

 

(vl-bb-set) & (vl-bb-ref)

 

never used them my self but seems they can provide some solution?

 

moshe

 

 

 

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.