Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2010-06

Updating an app "on the fly"

10 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

To what extent could a Lazarus app replace itself with a new version without interruption?

For example, if the main form had a menu at the top, synedit with popups and a status bar at the bottom, presumably much of the "intelligence" could be moved into dll/so libraries which could be closed and reopened.

Would the dynamic libraries be able to get at properties (e.g. main menu) of the visible components? Would they be able to display forms and dialogs on their own account?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Alexsander Rosa
to Mark Morgan Lloyd

My ERP has an auto-update feature in the main application (called "rnge2.exe"). The app does the following steps:

1) Check if there's a newer version. The new releases are replicated to each customer's branch.
2) If there's a newer version, download, md5sum-check and rename to "rnge2.new"
3) Execute an external application to swap the files; the app renames "rnge2.exe" to "rnge2.old", then renames "rnge2.new" to "rnge2.exe" and runs the new version.

Usually the old version's file is locked, so the external application has to wait for a while until it's released. In my case the app tries a couple times for it.

Mark Morgan Lloyd wrote 12 lines
To what extent could a Lazarus app replace itself with a new version without interruption? For example, if the main form had a menu at the top, synedit with popups and a status bar at the bottom, presumably much of the "intelligence" could be moved into dll/so libraries which could be closed and reopened. Would the dynamic libraries be able to get at properties (e.g. main menu) of the visible components? Would they be able to display forms and dialogs on their own account?
Alexsander da Rosa Twitter: @alexrosa

Reply by email

Mark Morgan Lloyd
to Alexsander Rosa
Alexsander Rosa wrote 14 lines
My ERP has an auto-update feature in the main application (called "rnge2.exe"). The app does the following steps: 1) Check if there's a newer version. The new releases are replicated to each customer's branch. 2) If there's a newer version, download, md5sum-check and rename to "rnge2.new" 3) Execute an external application to swap the files; the app renames "rnge2.exe" to "rnge2.old", then renames "rnge2.new" to "rnge2.exe" and runs the new version. Usually the old version's file is locked, so the external application has to wait for a while until it's released. In my case the app tries a couple times for it.

I was assuming that something like that would be needed for the dll/so, but the particular point I'm interested in is whether the main app /has/ to be restarted, or if there are hacks that can get around that.

I'm particularly thinking about Michael's earlier comment:

> There were several discussions, that when doing a DLL or .so with > Lazarus and using same with a Lazarus project, it's an issue that > the DLL will create it's own LCL "application" instance and thus > you can't easily do "normal" GUI stuff in the DLL/.so.

which suggests that there are limits as to what can go into a dll/so.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Thierry Coq
to Mark Morgan Lloyd

Hello,

Show quoted text 6 lines
I was assuming that something like that would be needed for the dll/so, but the particular point I'm interested in is whether the main app /has/ to be restarted, or if there are hacks that can get around that. which suggests that there are limits as to what can go into a dll/so.

In Delphi, it was possible to create components in a dynamic package, store the packages in a plug-in directory, and have the application look at the plug-in directory to load the various functions in the components.

Basically a dynamic package is just a dynamic library, with some <intelligent> work to identify the components inside. The dynamic loading of packages is not yet in FPC.

However, it is possible to emulate this behavior.
Look up the dynamic loading example here: http://www.tcoq.org/Lazarus.html I've tested that some time ago for windows and it seems to work. I haven't tested for Linux, though.
If you have any suggestions to improve that example, please send them ;-)

Best regards,
Thierry

Reply by email

Michael Van Canneyt
to Thierry Coq
Thierry Coq wrote 15 lines
Hello, > I was assuming that something like that would be needed for the dll/so, but > the particular point I'm interested in is whether the main app /has/ to be > restarted, or if there are hacks that can get around that. > which suggests that there are limits as to what can go into a dll/so. > In Delphi, it was possible to create components in a dynamic package, store the packages in a plug-in directory, and have the application look at the plug-in directory to load the various functions in the components. Basically a dynamic package is just a dynamic library, with some <intelligent> work to identify the components inside. The dynamic loading of packages is not yet in FPC.

I'm afraid that there is more to it than that.

For example, Packages share the same memory space and class inheritance tree. Libraries do not.

Show quoted text 6 lines
However, it is possible to emulate this behavior. Look up the dynamic loading example here: http://www.tcoq.org/Lazarus.html I've tested that some time ago for windows and it seems to work. I haven't tested for Linux, though. If you have any suggestions to improve that example, please send them ;-)

Your example will fail for instance when using strings, exceptions and classes.

Imagine the following function in the library:

Function CreateSomeComponent : TComponent;

Then the following will fail:

Var
   MyComponent : TComponent;
begin
   MyComponent:=CreateSomeComponent;
   if MyComponent is TComponent then
     begin
     // This code will never get executed.
     DoSomething;
     end;
end;

The code is never executed, because the TComponent class pointer points to the TComponent class as defined in the application, where the result returned by the function will descend from TComponent as defined in the library. The 'is' function cannot ever detect that, and will return false.

If you are using packages, then TComponent will be defined in the rtl package, and both the application and program will refer to the same definition in the rtl package, and so "MyComponent is TComponent" will work as intended.

Michael.

Reply by email

Mark Morgan Lloyd
to Michael Van Canneyt
Michael Van Canneyt wrote 8 lines
For example, Packages share the same memory space and class inheritance tree. Libraries do not. If you are using packages, then TComponent will be defined in the rtl package, and both the application and program will refer to the same definition in the rtl package, and so "MyComponent is TComponent" will work as intended.

Thanks both. So if I understand things correctly:

* A package uses the same LCL as the rest of the app.

* A library (standard dll/so) has a distinct LCL.

* Static package loading is currently supported.

* Package loading under control of the app (i.e. to implement plugins etc.) is not currently implemented.

I believe that I've dynamically-loaded (Linux) libusb under program control before now but I'd need to look closely at my code to be absolutely certain (and to work out how I did it). Somebody on CIX contributed a Win-32 dynamic-library object which can be trivially subclassed to describe e.g. the WinSock DLL.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Marco van de Voort
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 7 lines
> For example, Packages share the same memory space and class inheritance > tree. > Libraries do not. Thanks both. So if I understand things correctly: * A package uses the same LCL as the rest of the app.

Yes. Both code and state. The code part also contains the VMTs, which must be the same to make IS and AS work.

* A library (standard dll/so) has a distinct LCL.

Yes. Both code and state. (iow they can have different LCL versions)

Some people think that state is only the heapmanager, but it is also localisation, threadvars etc.

* Static package loading is currently supported.

Static packages are nothing more than a fancy word for groups of units.

* Package loading under control of the app (i.e. to implement plugins etc.) is not currently implemented.

Correct.

Show quoted text 5 lines
I believe that I've dynamically-loaded (Linux) libusb under program control before now but I'd need to look closely at my code to be absolutely certain (and to work out how I did it). Somebody on CIX contributed a Win-32 dynamic-library object which can be trivially subclassed to describe e.g. the WinSock DLL.

FPC loads foreign libraries externally all the time. But you also don't communicate on Pascal level between with them, and keep the RTL/libc states totally apart.

I refer to this as the "manual" solution. (which is btw not as easy as many people think, specially for large complicated frameworks like LCL)

The clue from packages (on the Pascal level) is (from http://wiki.freepascal.org/packages ):

that packagesallows to split up a program into modules by just grouping units, and satisfying unit dependancies. Not by reengineering the interface between modules. IOW it is transparent, and there are relative few things that can go wrong.

Reply by email

Thierry Coq
to Michael Van Canneyt: I'm afraid that there is more to it than that. For example, Packages share the same…

Dear Michael,
...

For example, Packages share the same memory space and class inheritance tree. Libraries do not.

You're absolutely right.

Your example will fail for instance when using strings, exceptions and classes.

Yes, the example will fail for classes and exceptions. You are correct.

But it does allow the dynamic loading of functions and procedures, and arrays of chars. The procedures and functions can be dynamically identified, using a sort of plug-in infrastructure, for example with a convention that every DLL declares a Register procedure.

It would provide for some sort of flexibility in the application.

I do remember it was possible to share strings in Delphi DLLs using a sharedmem unit. I'll have to check if this possible to do so with FPC and Lazarus. It would increase the flexibility.

Show quoted text 6 lines
If you are using packages, then TComponent will be defined in the rtl package, and both the application and program will refer to the same definition in the rtl package, and so "MyComponent is TComponent" will work as intended.

Yes, I wish very much we had this mechanism in FPC, and therefore in Lazarus.

Thank you for your comments.

Thierry

Reply by email

Mark Morgan Lloyd
to Marco van de Voort: Yes. Both code and state. The code part also contains the VMTs, which must be the same to…
Marco van de Voort wrote 6 lines
FPC loads foreign libraries externally all the time. But you also don't communicate on Pascal level between with them, and keep the RTL/libc states totally apart. I refer to this as the "manual" solution. (which is btw not as easy as many people think, specially for large complicated frameworks like LCL)

But isn't that static linkage, i.e. at the point the program is loaded, rather than dynamic?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Marco van de Voort
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 9 lines
> FPC loads foreign libraries externally all the time. But you also don't > communicate on Pascal level between with them, and keep the RTL/libc states > totally apart. > > I refer to this as the "manual" solution. (which is btw not as easy as many > people think, specially for large complicated frameworks like LCL) But isn't that static linkage, i.e. at the point the program is loaded, rather than dynamic?

Doesn't really matter. The point is that it has its own library dependancies, and the interface is not fully pascal enabled. Then it doesn't matter if it is statically linked (.a), dynamically linked at startup time, or dynamically loaded over loadlib.

IOW the division between mainprogram and lib is handcrafted, and the problems are the same (shared state+memmgr,VMT, no way to check mismatch in interface)

Reply by email