Moving from LSP to VLX

Moving from LSP to VLX

sjbarnes
Contributor Contributor
4,740 Views
10 Replies
Message 1 of 11

Moving from LSP to VLX

sjbarnes
Contributor
Contributor

I have a large group of legacy lisp programs to support. I want to move from deploying the raw lisp files to deploying a single VLX file, but this does not seem to be working for me.


I have used the MAKELISPAPP Wizard to create a VLX & successfully loaded that VLX with APPLOAD. However, on load the alphabetically first function runs without calling from the command line, then that command & all the other lisp commands do not work.

 

I suspect that the problem lies in the way that the lisp files are currently loaded. This is the current lisp file situation...

 

In acad.lsp there is this line to load a "master" lisp file > (LOAD "MASTER")

 

Within the master lisp file, the remaining lisp files are loaded as definitions using a generic load lisp function. This is an example lisp file definition...

 

(defun C:LFX(/ e l1 l1found l1b l1mess n)
    (E::load_file "LFX") ; see below for E::load_file definition
)

 

& this is the simplified generic load lisp function...

 

(defun E::load_file(gf)
    (if (findfile (strcat E::lisp gf ".lsp")) ; E::lisp is the lisp file directory
        (progn
            (command-s "_undo" "_be")
            (load (strcat E::lisp gf))
            (command-s "_undo" "_end")
        )

        (progn
            (prompt "\nIncorrect Software Installation...")
            (prompt "\n")(prompt (strcat E::lisp gf ".lsp not found "))
        )
    )
)

 

I think that loading the master lisp file from acad.lsp isn't the best method, but I can address that once I have the VLX alternative working.

 

These are my questions...

 

Can I deploy a single VLX without any FAS files?
Can I continue to use a master file to define the loading of subordinate files?
If so, do I need to change the E::load_file to load something other than ".lsp"?

0 Likes
4,741 Views
10 Replies
Replies (10)
Message 2 of 11

martti.halminen
Collaborator
Collaborator

First, acad.lsp is generally the wrong place to load Lisp stuff, by default that gets only run for the first .dwg you open in AutoCAD in that session. The other drawings have separate Lisp address spaces, so they see nothing done by acad.lsp.

 

acaddoc.lsp is run for every drawing.

 

Theoretically, you could create a .vlx that contains .lsp files, but why bother? The normal way is to compile the .lsp files to .fas so they are faster to load and faster to run.

 

The basic idea for .vlx is that all that is loaded at once, so all the separate (load ...) calls inside the files should be removed, you don't need to call those.

 

- Any kind of autoload trickery on top of .vlx is not worth the bother. We are loading our default library as .vlx via acaddoc.lsp, takes about half a second for 1700 defun calls.

Message 3 of 11

sjbarnes
Contributor
Contributor

Thanks Martti,

 

I am new to the idea of .VLX & .FAS, so I am a little confused.

 

With my current structure of MASTER.LSP & many subordinate.LSPs, what should I compile as VLX & what as FAS?

 

My current load calls from within my MASTER.LSP hold a lot of repetitive steps, like the undo commands in my simplified example above. Do I remove my "defun E::load_file(gf)" entirely from my MASTER.LSP? If I did that, I don't see how the repetitive steps could be achieved. Or do I just remove the "(load (strcat E::lisp gf))" line from within "defun E::load_file(gf)"? If "(load (strcat E::lisp gf))" is removed how would my "(defun C:LFX(/ e l1 l1found l1b l1mess n)" know what to do with LFX.FAS?

 

 

0 Likes
Message 4 of 11

martti.halminen
Collaborator
Collaborator

I work with VLIDE so I am not familiar with the details of Makelispapp, but it seems like it uses the same low-level machinery as the older system, so the general ideas should be the same.

 

The normal usage is that you define which .lsp files are used to build the application (+ possible .dcl etc files to include).

The system compiles all of those .lsp to .fas and concatenates the results to one .vlx file. So you only install the .vlx to users, the .fas files stay in your development environment.

 

From the program architecture viewpoint the result is the same as if you concatenated all the .lsp files into one file and loaded it. So your application already contains every defun in your files already loaded, no need to do any further loading, that will only confuse you.

 

So throw away (from the active system, keep a backup) the master.lsp file: the concept of subordinate files doesn't exist in a .vlx after it has been loaded.

 

You would only need undo definitions around loading if your .lsp files contain direct calls (not contained inside a defun) to modify the drawing (or calls functions which do that). While that is possible, it is a very bad idea, makes debugging rather painful, and as all the files are loaded at once, the end results may be quite odd.

 

So your .lsp files should preferably only contain function definitions, not any calls to those functions (apart from places lice acaddoc.lsp).

0 Likes
Message 5 of 11

sjbarnes
Contributor
Contributor

Thank you for clarifying the use of FAS / VLX files.

 

I am still struggling with what to do with the overall architecture of the lisp programs.

 

In addition to the numerous defuns that currently load the subordinate .lsp files, my MASTER.LSP does a lot of work required by most of the subordinate lisps, including setting up global variables for use between subordinate lisps. So I ready don't want to do away with it. I need the work within my MASTER.LSP to be complete before the subordinate lisps are used. Doing away with my MASTER.LSP would create a mass of duplicated code throughout my subordinate .lsp files & create a problem with global variables.

 

So I want to keep the subordinate lisp defuns in my MASTER.LSP, together with the global functionality.

 

I currently use my "E::load_file(gf)" function to load the .lsp files. I want to keep most of this structure, but it seems to me that this bold line within E::load_file(gf) is the key issue...

 

            (command-s "_undo" "_be")
            (load (strcat E::lisp gf))           < what is the alternative to this?
            (command-s "_undo" "_end")

 

If I do not load the subordinate lisps here, what do I do instead? I want to perform the steps before & after the "load alternative" each time the subordinate lisp is used. Do I have to replace this code from its single location in MASTER.LSP with the same code in each subordinate lisp?

0 Likes
Message 6 of 11

Sea-Haven
Mentor
Mentor

Maybe the "Autload" function will help, it also sounds like you need to make a defun/command call for all your lisps rather than just run on load, I dont use vlx but my understanding is its the same as issuing a "load" command so they are all ready to be used.

 

This for a menu

^c^c(load "myprog") myprog

becomes

^c^cmyprog

0 Likes
Message 7 of 11

martti.halminen
Collaborator
Collaborator

Obviously if your master.lsp does something else beyond loading files, it can't be totally removed, but the whole idea of .vlx is that the system loads all the files as one operation.

So any explicit load commands in the program referring to those files are superfluous, and won't work unless you also deliver the individual files, which is totally against the whole idea of collecting the stuff into a .vlx in the first place.

 

It sounds like your application is done interleaving loading files, executing programs, modifying the drawing etc.

 

It is possible to do this way, but the result is easily rather nasty to maintain and debug, and it is a bad fit to using a .vlx file. What happens with all those side-effects when you re-load the file during debugging?

 

When working with .vlx you do not have the concept of a subordinate file. All the files get loaded at once as one operation, you can't do anything between those. Better stop thinking in terms of files at all, you are living in one flat namespace where all the function definitions and global variables are visible at once.

 

A cleaner design would pack the global function definitions inside some initialization function, so you can decide what happens if you re-load the file during debugging: do you want to reset to original value, or do you want to keep the value the variable has at that moment? So the .lsp files would only contain (defun ...) calls and comments.

That way loading the file has no side effects requiring Undo markers around it.

 

The Undo marks (I prefer using vla-startundomark and vla-endundomark to calling command-s) would be inside the defuns, only where those are actually needed when the function modifies the drawing.

0 Likes
Message 8 of 11

martti.halminen
Collaborator
Collaborator

Sorry, in the previous reply

 

A cleaner design would pack the global function definitions inside some initialization function...

 

should be

 

A cleaner design would pack the global variable definitions inside some initialization function...

0 Likes
Message 9 of 11

john.uhden
Mentor
Mentor

A VLX file is supposed to be a collection of FAS files all wrapped into one.  If you haven't noticed, when building a VLX from multiple files, each LSP file is automatically "compiled" into a FAS before being wrapped up.  Plus you can include all the applicable DCL or other textual data files so that you need not have to use any paths at all.  They get included as text by their file name alone.

All the Lisp code within, from all sources, should contain nothing but function definitions.

Your problem may be that your MASTER.lsp file actually performs some operations other than defuns.  If that is true, then it should not be included in the VLX.  I don't know, because I've never tried it, but perhaps those operations are not automatically run when the VLX is loaded.  [Maybe @dbroad or @kent1cooper or @martti.halminen  could answer that.]  It sounds as if those operations should be included in your acaddoc.lsp file and all its defuns moved to a separate file that could be included in your VLX.  Having separated the wheat from the chaff, your acaddoc.lsp file could load MASTER.lsp rather than being MASTER.lsp, and it could load the VLX as well.  So, besides the required acaddoc.lsp you need only two other files to maintain and disseminate.

John F. Uhden

Message 10 of 11

doaiena
Collaborator
Collaborator

Upon loading a .vlx, ACAD will eval everything within, in order. You can execute code at load time, but you would need to structure your .vlx in a proper way.

 

1. - Create a project

2. - Arrange your .lsp files in order

3. - Build the project

 

You just need to pay attention when you order your .lsp files. If you need to call one of your own functions, you would need to set the right order in the project.

 

Project:

Func1.lsp

Func2.lsp

DoSomeStuff.lsp

Func3.lsp

Func4.lsp

Func5.lsp

 

Then your "DoSomeStuff.lsp" can contain:

(progn
(set some vars)

(Func1)

(do some  more things)

(Func2)
(maybe do some more things)
)

 

Just make sure you have everything you would need loaded before you start executing code within the project/vlx.

Message 11 of 11

sjbarnes
Contributor
Contributor

Thank you all for your generous suggestions.

 

I have worked my way through each of them, but have concluded for now that there is too much work involved in restructuring my legacy AutoLisp programs to work in a single VLX. The reward simply does not justify the time that would be involved.

 

So, I have decided for now to deploy multiple .FAS files rather than multiple .LSP files or a single .VLX file. This works simply for me.

 

As a long term goal, I still intend to create a single .VLX to replace the multiple .LSP/.FAS files, but I need to rationalise what remains in which files & consider whether some or all of these functions would be better placed in one of my associated .ARXs.

 

 

0 Likes