We need to create selection sets now and then with APIs that AutoCAD supports, e.g. AutoLISP, Visual LISP, ADS, ARX, ObjectARX, VBA, ActiveX API, and the modern .NET API. It will not cause issues if we only care about a few selection sets in a few databases but will likely if we create selection sets in a loop due to the fact that AutoCAD only maintains 128 global and static such selection sets.
It’s easy to see the behavior with some simple AutoLISP code:
(setq i 0)(repeat 128 (setq i (1+ i))(set (read (strcat "ss" (itoa i))) (ssget "X")))
If we launch AutoCAD, create a new drawing, add a circle to it, and run the above code, we will see things are fine.
Regenerating model.
AutoCAD menu utilities loaded.*Cancel*
Command:
Command:
Command: c CIRCLE Specify center point for circle or [3P/2P/Ttr (tan tan
radius)]:
Specify radius of circle or [Diameter]:
Command: (setq i 0)(repeat 128 (setq i (1+ i))(set (read (strcat "ss" (itoa
i))) (ssget "X")))
<Selection set: ec3>
If we close the previous drawing, create another one, add a circle as well, change the repeat number from 128 to 129 in the code and copy/paste it to the command line, and press enter, we will get an error saying “exceeded maximum number of selection sets”.
Regenerating model.
AutoCAD menu utilities loaded.
Command:
Command:
Command: c CIRCLE Specify center point for circle or [3P/2P/Ttr (tan tan
radius)]:
Specify radius of circle or [Diameter]:
Command: (setq i 0)(repeat 129 (setq i (1+ i))(set (read (strcat "ss" (itoa
i))) (ssget "X")))
; error: exceeded maximum number of selection sets
In addition, the limit applies to the whole AutoCAD session instead of each database/drawing. This can also be reproduced easily.
- Change the repeat number from 128 to 64 this time.
- Close all drawings, create a new one, add a circle, and copy/paste the code into the command line to run it.
- Keep the above drawing open, create another new one, add a circle as well, and run the same code.
- Keep the above two drawings open, create one more drawing, add a circle and run the following simpler code this time.
(setq ss129 (ssget "X"))
Here are the output in the three different drawing editor windows.
Drawing #1:
Regenerating model.
AutoCAD menu utilities loaded.
Command:
Command:
Command: c CIRCLE Specify center point for circle or [3P/2P/Ttr (tan tan
radius)]:
Specify radius of circle or [Diameter]:
Command: (setq i 0)(repeat 64 (setq i (1+ i))(set (read (strcat "ss" (itoa i)))
(ssget "X")))
<Selection set: fc8>
Drawing #2:
Regenerating model.
AutoCAD menu utilities loaded.
Command:
Command:
Command: c CIRCLE Specify center point for circle or [3P/2P/Ttr (tan tan
radius)]:
Specify radius of circle or [Diameter]:
Command: (setq i 0)(repeat 64 (setq i (1+ i))(set (read (strcat "ss" (itoa i)))
(ssget "X")))
<Selection set: fc8>
Drawing #3:
Regenerating model.
AutoCAD menu utilities loaded.
Command:
Command:
Command: c CIRCLE Specify center point for circle or [3P/2P/Ttr (tan tan
radius)]:
Specify radius of circle or [Diameter]:
Command: (setq ss129 (ssget "X"))
; error: exceeded maximum number of selection sets
It is simple to release the used selection sets back to the pool through setting the selection set variables as nil. In ADS/(Object)ARX, simply releasing the entity set objects can achieve the same goal.
In the coming post, we will continue to discuss this topic but in another API, AutoCAD .NET.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides a coder, Entity Jigger, to help us create entity jig code automatically, quickly and reliably.
Nice. Unless I'm wrong this limitation does not apply when using code like this:
(repeat 130 (if (ssget "X") (princ)))
Posted by: Jimmy Bergmark - JTB World | 09/07/2012 at 02:50 PM
JTB, you are right. Your code can call the ssget as many times as possible. From my understanding, LISP has a pretty nice internal mechanism to release the selection sets as soon as possible. Since the return value of the ssget is not stored into any variables, LISP frees the selection set right away. The situation is pretty similar if only one variable such as ‘ss’ is used in the loop. Only the final selection set will be kept, I think, and all previous ones have been released.
However, for AutoCAD .NET and ActiveX/COM APIs, things are quite different. We have to explicitly dispose of the SelectionSet or Delete/Free the AcadSelectionSet. The latest two posts discussed about these and demonstrated with code too.
Posted by: Spiderinnet1 | 09/07/2012 at 04:03 PM
Same is if you declare the variable it will be released.
You can do 128+ versions of the code below without problem
(defun test1 (/ ss1) (setq ss1 (ssget "X")))
Posted by: Jimmy Bergmark - JTB World | 09/08/2012 at 04:02 AM
Exactly. Because only one variable is defined in the test1 routine to hold the selection sets, the previous one will be released right away. That is the smart part of AutoLISP, I would say, as mentioned earlier.
That also explains why the test code in the post uses 128 different LISP variables (ss1 to ss128) to hold and keep the selection sets at the same moment and it reveals the 128 count limit of the selection sets.
Posted by: Spiderinnet1 | 09/08/2012 at 05:26 AM
Not sure I was clear but you can make as many versions like this as you want as long as the number of selection set variables are 128 or less within each function:
(defun test1 (/ ss1) (setq ss1 (ssget "X")))
(defun test2 (/ ss2) (setq ss2 (ssget "X")))
...
Posted by: Jimmy Bergmark - JTB World | 09/08/2012 at 11:26 AM
JTB, the limit applies when trying to keep more than 128 selection sets at the same time. When a selection set variable is reused in Lisp, it's previous holding will be released right away automatically and we don't have to explicitly free it by setting it as nil. That's a smart part in Lisp, as mentioned.
By the way, the ss1 and ss2 in your function definitions are local variables instead of global, and the selection sets they point to will be released when they go out of scope. That explains why more than 128 such functions can be defined but in each function no more than 128 selection set variables can be declared and kept valid values.
So using selection sets in a loop or function is not the real issue, but keeping more than 128 accessible at the same time is. We are on the same page.
Posted by: Spiderinnet1 | 09/08/2012 at 04:09 PM