Currently, if we have a library project, there's no way to test it without creating 2nd project which is an application. Should Lazarus implement something like V$ does? i.e. when "Run" is executed on a library project, the IDE then ask for an executable to run (the executable uses the library, so it will step into the library eventually). I have no idea whether gdb supports something like this or not.
Mailing lists / lazarus / 2012-09
"Running" a library
25 messages · 5 people · –
- MMark Morgan Lloyd 12
- SSven Barth 6
- JJuha Manninen 4
- Lleledumbo 2
- RRolf Grunsky 1
Reply by email Subscribe to this list Your subscription
Read-only archive. Use j and k to move between messages.
leledumbo wrote 6 lines
Couldn't this be specified as the "Launching application" parameter?
I think a fair question is whether a library can be built in such a way that it can also be started as a program, i.e. can be invoked in such a way as to test its own basic functionality.
Mark Morgan Lloyd wroteCouldn't this be specified as the "Launching application" parameter?
Actually it is defined in Run -> Run Parameters ... -> Host application
I think a fair question is whether a library can be built in such a way that it can also be started as a program, i.e. can be invoked in such a way as to test its own basic functionality.
How to create an automatic test program for it?
There are no general rules to do such thing.
Juha
P.S.
Not really related to this question but maybe 2 years ago Lazarus still allowed to "run" a library project.
It was a bug, the library binary was treated like any program binary and it crashed of course.
It is fixed now.
Juha Manninen wrote 5 lines
I was thinking about the case where some sort of wrapper was needed to do something sensible with the library, e.g. to call a "magic number" function as a basic test of what interface it exposed.
Show quoted text 6 lines
No, I was wondering about the extent to which a library could be defined such that it was also runnable as a program.
Show quoted text 6 lines
But /why/ did it crash? Can a library be written so that it doesn't crash if invoked as a program?
Mark Morgan Lloyd wroteNo, I was wondering about the extent to which a library could be defined such that it was also runnable as a program.
A library cannot be run alone.
However there 2 kinds of libraries: a dynamic library (.dll, .so) and a static library.
You can test your library code by creating a program that links the code statically, or uses its code units directly.
Once it works well then you can make a dynamic library, but it still needs some extra testing.
For example dynamic strings cannot be used across the calls, GUI component usage is limited etc.
For this testing you must create the "Host application" which links dynamically to the library.
Juha
Juha Manninen wrote 10 lines
I'm aware of the technology, I've been using it intermittently for 20 years or so.
/Why/ can't a library be run standalone? We're already at the position that an executable can decide whether it's been invoked from a shell or the GUI and behave as appropriate, so why can't it decide whether it's being run as a program or being initialised as a library?
Once it works well then you can make a dynamic library, but it still needs some extra testing. For example dynamic strings cannot be used across the calls,
Works here, subject to explicit use of cmem.
GUI component usage is limited etc.
Works here as far as I've tested (i.e. merging menus from a shared library into the main program, using dialog(ue)s defined in the shared library and so on).
For this testing you must create the "Host application" which links dynamically to the library.
Again, /why/?
On Fri, Sep 14, 2012 at 10:34 PM, Mark Morgan Lloyd A library cannot be run alone.…
A library cannot be run alone.
However there 2 kinds of libraries: a dynamic library (.dll, .so) and a static library.
You can test your library code by creating a program that links the code statically, or uses its code units directly.
Ehm... FPC can't create static libraries... anymore :)
Currently, if we have a library project, there's no way to test it without creating 2nd…
leledumbo wrote 7 lines
It's been a very long time since I looked at this, and this is specific to Windows. An exe and dll have the same basic structure, the difference is that an exe can not export entry points and part of the startup will initialize the stack and data segments. On the other hand, any procedure called in a dll will assume that the stack pointer and segment registers have been already set up. Also, I believe that there is only a single entry point in an exe. Windows does provide a method to run a dll as a program but I would assume that you have to pass the procedure in the dll that you want to run. As I said this is from vague memory so the details are fuzzy. At a minimum, to run a procedure in the dll you will need some code to set up stack and data segments.
Rolf Grunsky wrote 11 lines
I can't speak for the current PE format, but working from memory (i.e. stuff I've done) an NE-format .exe could be built exposing multiple named entry points: I've used that facility with older tools to generate a file which could then be bound with descriptors etc. for a '386 running in protected mode.
Whether such a hybrid format actually makes sense to a standard operating system is, of course, a different question. And whether there's a methodology which would allow a hybrid program/library to be useful (e.g. by having the program entry point test the functionality of the library entry points) is another.
I'm aware of the technology, I've been using it intermittently for 20 years or so. /Why/…
Mark Morgan Lloyd wrote/Why/ can't a library be run standalone? We're already at the position that an executable can decide whether it's been invoked from a shell or the GUI and behave as appropriate, so why can't it decide whether it's being run as a program or being initialised as a library?
Ok, true, the compiler COULD support it but currently it does not.
Show quoted text 5 lines
IIRC the published API from a shared library cannot use normal dynamic pascal strings. You must use PChar.
Show quoted text 5 lines
I have not put GUI components into libraries myself but there are bug reports that show problems.
http://bugs.freepascal.org/view.php?id=18624
http://bugs.freepascal.org/view.php?id=15126
http://bugs.freepascal.org/view.php?id=7181
http://bugs.freepascal.org/view.php?id=7182
http://bugs.freepascal.org/view.php?id=1866
From leledumbo: Ehm... FPC can't create static libraries... anymore :)
Is it so? I forgot that but linking with compiled unit files is almost the same thing.
Now suppose the compiler could create a library which can be run as a program. What is a benefit compared to a separate program using the same code? There will be 2 binaries but for testing purposes that is OK.
In any case you must also test the final shared library as a library before sending it to users.
Regards,
Juha
Juha Manninen wrote 7 lines
I'm definitely passing strings between a .so and main program, both written using Lazarus. So e.g. a frontend program can call these from the backend:
function LoadConfiguration(base: string= ''): boolean;
function BackendAboutText: string;and the backend can call these from the fontend:
procedure FrontendSetButtonLegendSafe(index: integer; const legend: string);
procedure FrontendOutputWriteSafe(const str: unicodestring; fg: TColor=
clBlack; bg: TColor= clDefault);>> GUI component usage is limited etc. > Works here as far as I've tested (i.e. merging menus from a shared library > into the main program, using dialog(ue)s defined in the shared library and > so on).
I need to correct an inaccuracy: I should have said displaying messageboxes rather than using dialog(ue)s.
Show quoted text 8 lines
Noted, and obviously I defer to your experience and direct involvement. But it is possible to define the structure of displayable objects in a shared library, and then to copy them when needed.
I'm aware of the technology, I've been using it intermittently for 20 years or so. /Why/…
Mark Morgan Lloyd wrote 19 lines
A library and an application have different entry point signatures. Take Windows for example. There the entry point for applications is "procedure EntryPoint; stdcall;" while for DLLs it is "procedure EntryPoint(aHinstance: PtrInt; aDLLReason: Word; aDLLParam: Pointer); stdcall;". Additionally the entry point of a DLL is called multiple times (once the process loads the library, every time a new thread is created and destroyed and once the process unloads the library) while the entry point of an application is only called once. Also AFAIK Windows does not let you run binaries that are flagged as "DLL". That's the reason why there is a program called "rundll32" ;) [though it expects an exported function with a certain signature...]
Regards,
Sven
It's been a very long time since I looked at this, and this is specific to Windows. An…
Rolf Grunsky wrote 24 lines
Note: You can export symbols from a program (this even works with FPC), but you should only do a LoadLibrary for that application from a library that is loaded by that application to avoid that the entry point is called ;) The only program that I'm aware of that utilizes this is the kernel itself: ntoskrnl.exe is linked to by device drivers.
Regards,
Sven
A library and an application have different entry point signatures. Take Windows for…
Sven Barth wrote 16 lines
Thanks for that, interesting and potentially useful. Can you comment on the situation for ELF-based OSes such as Linux?
Mark Morgan Lloyd wrote 22 lines
No, I'm not experienced enough with ELF, though I want to change that somewhen in the future (but not now :P )
Regards,
Sven
I'm definitely passing strings between a .so and main program, both written using…
Mark Morgan Lloyd wroteI'm definitely passing strings between a .so and main program, both written using Lazarus. So e.g. a frontend program can call these from the backend:
Maybe my knowledge was outdated and the problem is fixed, or maybe it happened only when calling the library from other languages than pascal.
Anyway, thanks for the correction.
Juha
Juha Manninen wrote 9 lines
I think http://mantis.freepascal.org/view.php?id=22386 is relevant. The current position is certainly good enough to be useful, although as others have pointed out it's not possible to write fully-graphical backends.
A library and an application have different entry point signatures. Take Windows for…
Sven Barth wrote 16 lines
Assuming for a moment that a binary can be built that is basically an executable but also exports library-style entry points, and which could be loaded into memory using DynLib or whatever: could the initialisation function be told to return fast and cleanly if it detected that it wasn't being run as a program? In that case, the caller could use DynLib to load it and then invoke a different entry point explicitly to handle initialisation.
Hypothetical case in which this sort of thing could be useful: if run as a program the library outputs a .inc or .h file describing its exports.
Mark Morgan Lloyd wrote 27 lines
You are able to define exports from a program. And you can also load the program binary using LoadLibrary from a library that is already loaded from that program (because the entry point is not called then), but you can not build an application that can be used also as a dynamic library, because as I already wrote the entry point signatures are different and thus if you would e.g. use the DLL's signature for the program your code would expect parameters (aHinstance, aDLLReason and aDLLParam) where the OS did not pass you anything ( => stack corruption).
Regards,
Sven
Sven Barth wrote 32 lines
I'm already calling from a loaded library back into the calling program using that technique. What happens if a library tries to load a /different/ program: is the main entry point called and are the subsidiary entry points available?
Show quoted text 6 lines
Although the called code might be able to determine that the parameters aren't valid and react accordingly, and being stdcall (unless my understanding is outdated) it's the caller that restores the stack state.
Mark Morgan Lloyd wrote 40 lines
I currently only have one answer for that: try it and see what happens.
Show quoted text 11 lines
In cdecl it's the caller, because of varargs functions which are not possible with e.g. stdcall as there the callee is responsible.
Regards,
Sven
Sven Barth wrote 47 lines
I have now checked ReactOS' code: if you load an exe that is not the main executable then the entry point won't be it seems that you can load such executables and call functions from them, but in the case of FPC you might be screwed (or at least very restricted) as the initialization sections of the units won't be run (this includes the system unit which initializes the heap, io, etc.).
Regards,
Sven
I currently only have one answer for that: try it and see what happens. In cdecl it's the…
Sven Barth wrote 47 lines
Will do, but not today. I'll report back.
Show quoted text 14 lines
Thanks for refreshing my memory.
I have now checked ReactOS' code: if you load an exe that is not the main executable then…
Sven Barth wrote 18 lines
Thanks for that, I'm currently looking at the situation on x86 Linux since I think it's worth progressing this while the thread's fresh.
The fact that the heap etc. wouldn't be initialised had already occurred to me. Is there any way to fake this?
Mark Morgan Lloyd wrote 9 lines
I don't think this is doing to work on Linux. I know that a shared library can open the main program by referring to '' (and am using this), but trying to pass the name of a different program fails with "No such file or directory" and no useful error message from dl.
