Sign in Join

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

Mailing lists / fpc-devel / 2006-05

a shared library suggestion

10 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

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

peter green

What i'd like to see is compiler level support for loading dynamic libraries and binding thier functions on demand.

this would mean a lot more flexibility. New features could be used without breaking compatibility with older versions of the library. Version and naming issues could be dealt with at runtime making the final compiled binaries portable!

its possible to load libraries on demand now by using dlopen/dlsym (or thier windows equivilents loadlibrary and getprocaddress) manually but its a pita to do involving writing a lot of wrappers manually.

Reply by email

Joost van der Sluis
to peter green
peter green wrote
What i'd like to see is compiler level support for loading dynamic libraries and binding thier functions on demand.

Like the database-base packages do? (example:
packages/base/ibase/ibase60dyn.pp)

But here I've used wrappers. But it's not very difficult to make a parser that create those. (I had one, but lost a part of it)

Regards,
Joost.

Reply by email

peter green
to Joost van der Sluis
Show quoted text 6 lines
> What i'd like to see is compiler level support for loading dynamic libraries > and binding thier functions on demand. Like the database-base packages do? (example: packages/base/ibase/ibase60dyn.pp)

ok that unit really confuses me, it seems to treat procedures declared external as if they were pointers. what exactly is going on?!

Reply by email

Joost van der Sluis
to peter green
peter green wrote 8 lines
> > What i'd like to see is compiler level support for loading > dynamic libraries > > and binding thier functions on demand. > > Like the database-base packages do? (example: > packages/base/ibase/ibase60dyn.pp) ok that unit really confuses me, it seems to treat procedures declared external as if they were pointers. what exactly is going on?!

It defines the procedures as variables, like this:

var
  isc_attach_database : function(param:integer):integer; extdecl;

And then it assigns the external-procedure to it - at runtime - with this commands:

begin
  IBaseLibraryHandle:=LoadLibrary(LibraryName);
  pointer(isc_attach_database) :=
     GetProcedureAddress(IBaseLibraryHandle,'isc_attach_database');
end;

And when that is done, you can simply call:

i := isc_attach_database(param);

Maybe you could get confused by the ifdef's and 'extdecl' term. 'extdecl' is just a macro defined as cdecl or stdcall, dependent on the OS.

And the include-file can be used for dynamical loading, and statical. So all proceduress are defined twice. Once statical and once dynamical. Which one is compiled is dependent on the LinkDynamically define.

Joost.

Reply by email

peter green
to Joost van der Sluis

yeah that technique requires far less stubs but it means that the coder has to manually call an init function.

also how does your code respond if one of the entry points isn't found?

Show quoted text 51 lines
-----Original Message----- From: Behalf Of Joost van der Sluis Sent: 09 May 2006 23:26 To: FPC developers' list Subject: RE: [fpc-devel] a shared library suggestion On Tue, 2006-05-09 at 21:26 +0100, peter green wrote: > > > What i'd like to see is compiler level support for loading > > dynamic libraries > > > and binding thier functions on demand. > > > > Like the database-base packages do? (example: > > packages/base/ibase/ibase60dyn.pp) > ok that unit really confuses me, it seems to treat procedures declared > external as if they were pointers. what exactly is going on?! It defines the procedures as variables, like this: var isc_attach_database : function(param:integer):integer; extdecl; And then it assigns the external-procedure to it - at runtime - with this commands: begin IBaseLibraryHandle:=LoadLibrary(LibraryName); pointer(isc_attach_database) := GetProcedureAddress(IBaseLibraryHandle,'isc_attach_database'); end; And when that is done, you can simply call: i := isc_attach_database(param); Maybe you could get confused by the ifdef's and 'extdecl' term. 'extdecl' is just a macro defined as cdecl or stdcall, dependent on the OS. And the include-file can be used for dynamical loading, and statical. So all proceduress are defined twice. Once statical and once dynamical. Which one is compiled is dependent on the LinkDynamically define. Joost. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

L505
to peter green
yeah that technique requires far less stubs but it means that the coder has to manually call an init function. also how does your code respond if one of the entry points isn't found?

Myself I use

{$IFDEF DEBUG}
 if getprocaddress(somefunc) = nil then write('somefunc getproc error');
{$ENDIF DEBUG}

It does get very very tedious to type all this out for large libraries with 50 functions or so.
If you want to economize the size of the library you turn off the {$DEFINE DEBUG}

Do you know that FPC will have a Package system available in fpc 2.1.1, sooner or later? It will require shipping the RTL in a package, I think - which means we get into Package hell like BPL's offered. I'd rather have the ability to load one package and not have to ship the RTL as a package.

Reply by email

Michael Van Canneyt
to peter green: yeah that technique requires far less stubs but it means that the coder has to manually…
peter green wrote
yeah that technique requires far less stubs but it means that the coder has to manually call an init function.

No.
- This can be put in the initialization of the unit.
- It can be called by components that need it. SQLDB does it like that.

also how does your code respond if one of the entry points isn't found?

It leaves the pointer empty. This is needed, because some entry points simply don't exist in some versions of DLL's

Michael.

Reply by email

Marco van de Voort
to L505: Myself I use {$IFDEF DEBUG} if getprocaddress(somefunc) = nil then write('somefunc…
Show quoted text 9 lines
It does get very very tedious to type all this out for large libraries with 50 functions or so. If you want to economize the size of the library you turn off the {$DEFINE DEBUG} Do you know that FPC will have a Package system available in fpc 2.1.1, sooner or later? It will require shipping the RTL in a package, I think - which means we get into Package hell like BPL's offered. I'd rather have the ability to load one package and not have to ship the RTL as a package.

That's the problem. The package _also_ requires the RTL. But maybe Borland only choice the "easy" solution and are there several.

Moreover, for the "hell" FPC it would be worse. There are maybe 20 Delphi versions, but way more Free Pascal versions, specially if you count the Lazarus intermediate releases based on snapshot versions

Reply by email

Michalis Kamburelis
to peter green: yeah that technique requires far less stubs but it means that the coder has to manually…
peter green wrote
yeah that technique requires far less stubs but it means that the coder has to manually call an init function.

Not necessarily, because you can load all addresses in initialization section of the unit. That's what I do in my various wrappers.

also how does your code respond if one of the entry points isn't found?

, in this case the error is ignored (i.e. the
entry point is left as "nil", this will result in error at runtime if you try to call this function). But the technique is flexible --- you could as well check GetProcedureAddress result and raise exception like "entry point %s missing" if it's nil.

This technique also allows you to try to load from various dll/so names, if you're not sure what the precise lib name will be on user system. This is even used ibase60dyn, as it tries to load first fbclib then (if that fails) gdslib (e.g. 'libfbclient.so' or 'libgds.so' on Unix). So it will work with both Interbase and "clean" (not forced to be compatible with Interbase) Firebird installations.

Michalis

Reply by email

L505
to Marco van de Voort: That's the problem. The package _also_ requires the RTL. But maybe Borland only choice…
> Do you know that FPC will have a Package system available in fpc 2.1.1, sooner or

later?

> It will require shipping the RTL in a package, I think - which means we get into

Package

> hell like BPL's offered. I'd rather have the ability to load one package and not have

to

> ship the RTL as a package. That's the problem. The package _also_ requires the RTL. But maybe Borland only choice the "easy" solution and are there several.

I think you can manually load a single BPL - I haven't tried myself - but this is manual work again whereas we are talking about automated solutions I guess..

i.e. loadlibrary('somebpl.bpl');

(I wonder if you can manually load an FPC package.. ?)

Reply by email