"Running" a library

classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

"Running" a library

leledumbo
Administrator
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.
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
leledumbo wrote:
> 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.

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
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Juha Manninen
On Fri, Sep 14, 2012 at 7:56 PM, Mark Morgan Lloyd
<[hidden email]> wrote:
> Couldn'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.

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
Juha Manninen wrote:
> On Fri, Sep 14, 2012 at 7:56 PM, Mark Morgan Lloyd
> <[hidden email]> wrote:
>> Couldn't this be specified as the "Launching application" parameter?
>
> Actually it is defined in Run -> Run Parameters ... -> Host application

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.

>> 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.

No, I was wondering about the extent to which a library could be defined
such that it was also runnable as a program.

> 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.

But /why/ did it crash? Can a library be written so that it doesn't
crash if invoked as a program?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Juha Manninen
On Fri, Sep 14, 2012 at 10:34 PM, Mark Morgan Lloyd
<[hidden email]> wrote:
> No, 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

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
Juha Manninen wrote:

> On Fri, Sep 14, 2012 at 10:34 PM, Mark Morgan Lloyd
> <[hidden email]> wrote:
>> No, 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.

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/?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

leledumbo
Administrator
In reply to this post by Juha Manninen
> 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 :)
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Rolf Grunsky
In reply to this post by leledumbo
On 12-09-14 10:39 AM, leledumbo wrote:
> 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.
>

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.


--
                                TRUTH in her dress finds facts too tight.
                                In fiction she moves with ease.
                                Stray Birds by Rabindranath Tagore

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
Rolf Grunsky wrote:

> 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.

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.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Juha Manninen
In reply to this post by Mark Morgan Lloyd
On Sat, Sep 15, 2012 at 12:47 AM, Mark Morgan Lloyd
<[hidden email]> 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.


>> 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.

IIRC the published API from a shared library cannot use normal dynamic
pascal strings. You must use PChar.


>> 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 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

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
Juha Manninen wrote:

>>> 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.
>
> IIRC the published API from a shared library cannot use normal dynamic
> pascal strings. You must use PChar.

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.

> 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

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.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Sven Barth
In reply to this post by Mark Morgan Lloyd
On 14.09.2012 23:47, Mark Morgan Lloyd wrote:

> Juha Manninen wrote:
>> On Fri, Sep 14, 2012 at 10:34 PM, Mark Morgan Lloyd
>> <[hidden email]> wrote:
>>> No, 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.
>
> 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?

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

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Sven Barth
In reply to this post by Rolf Grunsky
On 15.09.2012 07:10, Rolf Grunsky wrote:

> On 12-09-14 10:39 AM, leledumbo wrote:
>> 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.
>>
>
> 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.
>
>

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

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
In reply to this post by Sven Barth
Sven Barth 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?
>
> 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...]

Thanks for that, interesting and potentially useful. Can you comment on
the situation for ELF-based OSes such as Linux?

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Sven Barth
On 15.09.2012 11:48, Mark Morgan Lloyd wrote:

> Sven Barth 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?
>>
>> 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...]
>
> Thanks for that, interesting and potentially useful. Can you comment on
> the situation for ELF-based OSes such as Linux?
>

No, I'm not experienced enough with ELF, though I want to change that
somewhen in the future (but not now :P )

Regards,
Sven

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Juha Manninen
In reply to this post by Mark Morgan Lloyd
On Sat, Sep 15, 2012 at 11:52 AM, Mark Morgan Lloyd
<[hidden email]> wrote:
> 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:

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

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
Juha Manninen wrote:
> On Sat, Sep 15, 2012 at 11:52 AM, Mark Morgan Lloyd
> <[hidden email]> wrote:
>> 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:
>
> 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.

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.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
In reply to this post by Sven Barth
Sven Barth 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?
>
> 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...]

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
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Sven Barth
On 15.09.2012 12:36, Mark Morgan Lloyd wrote:

> Sven Barth 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?
>>
>> 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...]
>
> 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.
>

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

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] "Running" a library

Mark Morgan Lloyd
Sven Barth wrote:

> On 15.09.2012 12:36, Mark Morgan Lloyd wrote:
>> Sven Barth 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?
>>>
>>> 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...]
>>
>> 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.
>>
>
> 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),

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?

> 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).

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
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]

--
_______________________________________________
Lazarus mailing list
[hidden email]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
12