windows.GetProcAddress() vs DynLibs.GetProcAddress()

classic Classic list List threaded Threaded
60 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Ewald-2
<base href="x-msg://21/">
On 13 Jan 2014, at 17:33, Fred van Stappen wrote:

Hello and many thanks to help.

Here demo to show the problem (i hope).

>> https://sites.google.com/site/fiensprototyping/dynlib_vs_windows.zip


in the dynlibs version, why do you use `PChar(1)` or `PChar(2)` [or ....] instead of the name of the function as the second argument in GetProcAddress()? Perhaps try `GetProcAddress(LibHandle,  'soundtouch_clear');` on line 54 and modify the rest in a similar fashion?

Hope it helps.

--
Ewald


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs
From: [hidden email]
Date: Mon, 13 Jan 2014 21:25:27 +0100
To: [hidden email]
Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress()


On 13 Jan 2014, at 17:33, Fred van Stappen wrote:

Hello and many thanks to help.

Here demo to show the problem (i hope).

>> https://sites.google.com/site/fiensprototyping/dynlib_vs_windows.zip


in the dynlibs version, why do you use `PChar(1)` or `PChar(2)` [or ....] instead of the name of the function as the second argument in GetProcAddress()? Perhaps try `GetProcAddress(LibHandle,  'soundtouch_clear');` on line 54 and modify the rest in a similar fashion?

Hope it helps.

--
Ewald


_______________________________________________ fpc-pascal maillist - [hidden email] http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Yep Ewald, many thank to help us ( and me).

The SoundTouch.dll uses index to call the procedures.

Like that :
 [Ordinal/Name Pointer]
    [   0] soundtouch_clear
    [   1] soundtouch_createInstance
    [   2] soundtouch_destroyInstance

>> try `GetProcAddress(LibHandle,  'soundtouch_clear');

I have try that, but it does not work...`


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Ewald-2
<base href="x-msg://3/">
On 13 Jan 2014, at 23:06, Fred van Stappen wrote:

The SoundTouch.dll uses index to call the procedures.

Like that :
 [Ordinal/Name Pointer]
    [   0] soundtouch_clear 
    [   1] soundtouch_createInstance 
    [   2] soundtouch_destroyInstance


That explains why it works in windows probably, there you can specify an index to go with your exported procedures IIRC. I don't know if this is possible though on *nix.

Have a look at http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx ; there it says that if you pass in a pointer with  value where the high order word is zero, it is interpreted as an ordinal value. The same does not apply to the dynlibs version.


>> try `GetProcAddress(LibHandle,  'soundtouch_clear');

I have try that, but it does not work...`


What is the result of the call (GetProcAddress)? nil? if so then try to find the names of the symbols defined in the shared object (nm comes to mind).

Now, for the windows version, I don't know what underlying mechanism dynlibs uses under windows, so I'm afraid I can't really comment on that platform, except that you could try a similar approach as on linux (use symbol names instead of indices). OTOH it could (?) be that the the compiler inserts code to typecast PChar(1) to a string, which could result in an access violation (try `var a: string; a:= pchar(1);` to try it out ;-) ).

--
Ewald


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

wkitty42
In reply to this post by fredvs

fred, can you please adjust your quoting to use the standard '>' for previous
responses and then add your response below? you do add your response below but
the quote is the exact of the previous and it is very hard to read only your
responses when the previous is not prefixed by '>'... thanks! ;)

--
NOTE: No off-list assistance is given without prior approval.
       Please keep mailing list traffic on the list unless
       private contact is specifically requested and granted.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Sven Barth-2
In reply to this post by Ewald-2

Am 14.01.2014 00:12 schrieb "Ewald" <[hidden email]>:
>
>
> On 13 Jan 2014, at 23:06, Fred van Stappen wrote:
>
>> The SoundTouch.dll uses index to call the procedures.
>>
>> Like that :
>>  [Ordinal/Name Pointer]
>>     [   0] soundtouch_clear 
>>     [   1] soundtouch_createInstance 
>>     [   2] soundtouch_destroyInstance
>>
>
> That explains why it works in windows probably, there you can specify an index to go with your exported procedures IIRC. I don't know if this is possible though on *nix.

No, ordinals are not supported on non-Windows (or more precisely non-PE) systems.

>
>> >> try `GetProcAddress(LibHandle,  'soundtouch_clear');
>>
>> I have try that, but it does not work...`
>>
>
> What is the result of the call (GetProcAddress)? nil? if so then try to find the names of the symbols defined in the shared object (nm comes to mind).
>
> Now, for the windows version, I don't know what underlying mechanism dynlibs uses under windows, so I'm afraid I can't really comment on that platform, except that you could try a similar approach as on linux (use symbol names instead of indices). OTOH it could (?) be that the the compiler inserts code to typecast PChar(1) to a string, which could result in an access violation (try `var a: string; a:= pchar(1);` to try it out ;-) ).

The Windows version of dynlibs directly uses the Windows functions. The only difference is that it takes an AnsiString as argument and thus one can't pass an ordinal value.

Maybe an overload could be added to load functions by ordinal on Windows and which simply returns Nil on other platforms.

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Marco van de Voort
In our previous episode, Sven Barth said:
>
> Maybe an overload could be added to load functions by ordinal on Windows
> and which simply returns Nil on other platforms.

I thought the index feature originated in win3.x and was mostly considered
deprecated by MS?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Sven Barth-2

Am 14.01.2014 12:04 schrieb "Marco van de Voort" <[hidden email]>:
>
> In our previous episode, Sven Barth said:
> >
> > Maybe an overload could be added to load functions by ordinal on Windows
> > and which simply returns Nil on other platforms.
>
> I thought the index feature originated in win3.x and was mostly considered
> deprecated by MS?

Names are optional while ordinals are not. If you look for example at urlmon.dll or shlwapi.dll then you'll see quite some functions that are exported by ordinal only (FPC can't do that as it always adds at least a '' name). Also MSDN nowhere mentions that the NONAME attribute for Def files is deprecated.
(also import by ordinal is slightly faster)

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs
In reply to this post by Ewald-2
>Now, for the windows version, I don't know what underlying mechanism
>dynlibs uses under windows, so I'm afraid I can't really comment on that >platform, except that you could try a similar approach as on linux (use symbol
>names instead of indices). OTOH it could (?) be that the the compiler inserts
>code to typecast PChar(1) to a string, which could result in an access violation
> (try `var a: string; a:= pchar(1);` to try it out ;-) ).
>Ewald

Many thanks Ewald.
I decided to use windows unit for Windows (it works so...).
Sadly, for Linux, i do not find a solution...
Many thanks.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs
In reply to this post by wkitty42
> fred, can you please adjust your quoting to use the standard '>' for previous
> responses and then add your response below? you do add your response below but
> the quote is the exact of the previous and it is very hard to read only your
> responses when the previous is not prefixed by '>'... thanks! ;)

Oops, really sorry, i answer directly from hotmail.com...
I tought that M$ will do it automatic.
I will check it in future...

Thanks to note it.

Fred

 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

hinst
In reply to this post by fredvs
I identified the problem........
Take a look at the function declaration plz:
Function GetProcAddress(Lib : TlibHandle; const ProcName : AnsiString) : Pointer; // from dynlibs
It internally uses this function:
Function GetProcedureAddress(Lib : TLibHandle; const ProcName : AnsiString) : Pointer;

I changed type of ProcName parameter from const AnsiString to PChar and it _suddenly started to work.
Looks like FPC compiler generate some additional instructions for AnsiString which fail to work properly with invalid pointer. Perhaps it can not dereference pointer to 1. I don't know why it happens. It is strange because FPC should (perhaps) do reference counting only for arguments of type AnsiString but not _const_ AnsiString. It is also possible that reference counting happens here:

Function GetProcedureAddress(Lib : TLibHandle; const ProcName : AnsiString) : Pointer;
begin
  Result:=Windows.GetProcAddress(Lib,PChar(ProcName) { <- here} );

at PChar(ProcName)

@Fred van Stappen: you can create a copy of dynlibs unit, then make necessary changes to it (change type of ProcName from AnsiString to PChar or PAnsiChar), then place it into folder where your other sources are located; then your modified unit will get compiled instead of precompiled unit from FPC RTL.

@Fred van Stappen: also please note that including sysutils unit in your application may help to identify crashes because it enables exception support on higher level; and instead of RuntimeError message in console window you will get a more detailed exception message; you may also wish enable -gl command switch for FPC to get specific line numbers as well.

14.01.2014, 16:21, "Fred van Stappen" <[hidden email]>:

>>Now, for the windows version, I don't know what underlying mechanism
>>dynlibs uses under windows, so I'm afraid I can't really comment on that >platform, except that you could try a similar approach as on linux (use symbol
>>names instead of indices). OTOH it could (?) be that the the compiler inserts
>>code to typecast PChar(1) to a string, which could result in an access violation
>> (try `var a: string; a:= pchar(1);` to try it out ;-) ).>Ewald
>
> Many thanks Ewald.
> I decided to use windows unit for Windows (it works so...).
> Sadly, for Linux, i do not find a solution...
> Many thanks.
>
> ,
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Tomas Hajny-2
In reply to this post by Sven Barth-2
On Tue, January 14, 2014 09:24, Sven Barth wrote:
> Am 14.01.2014 00:12 schrieb "Ewald" <[hidden email]>:
>> On 13 Jan 2014, at 23:06, Fred van Stappen wrote:
>>
>>> The SoundTouch.dll uses index to call the procedures.
 .
 .
> No, ordinals are not supported on non-Windows (or more precisely non-PE)
> systems.

This statement certainly does not cover all FPC targets, because ordinals
are also used at least under OS/2 (which is a "non-PE" system).


> The Windows version of dynlibs directly uses the Windows functions. The
> only difference is that it takes an AnsiString as argument and thus one
> can't pass an ordinal value.
>
> Maybe an overload could be added to load functions by ordinal on Windows
> and which simply returns Nil on other platforms.

...except OS/2 (and possibly some others)... ;-)

Tomas


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Sven Barth-2

Am 14.01.2014 14:02 schrieb "Tomas Hajny" <[hidden email]>:
>
> On Tue, January 14, 2014 09:24, Sven Barth wrote:
> > Am 14.01.2014 00:12 schrieb "Ewald" <[hidden email]>:
> >> On 13 Jan 2014, at 23:06, Fred van Stappen wrote:
> >>
> >>> The SoundTouch.dll uses index to call the procedures.
>  .
>  .
> > No, ordinals are not supported on non-Windows (or more precisely non-PE)
> > systems.
>
> This statement certainly does not cover all FPC targets, because ordinals
> are also used at least under OS/2 (which is a "non-PE" system).
>
>
> > The Windows version of dynlibs directly uses the Windows functions. The
> > only difference is that it takes an AnsiString as argument and thus one
> > can't pass an ordinal value.
> >
> > Maybe an overload could be added to load functions by ordinal on Windows
> > and which simply returns Nil on other platforms.
>
> ...except OS/2 (and possibly some others)... ;-)

Ok, ok, but at least Unix systems don't support ordinals :P

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Sven Barth-2
In reply to this post by fredvs

Am 14.01.2014 13:21 schrieb "Fred van Stappen" <[hidden email]>:
>
> >Now, for the windows version, I don't know what underlying mechanism
> >dynlibs uses under windows, so I'm afraid I can't really comment on that >platform, except that you could try a similar approach as on linux (use symbol
> >names instead of indices). OTOH it could (?) be that the the compiler inserts
> >code to typecast PChar(1) to a string, which could result in an access violation
> > (try `var a: string; a:= pchar(1);` to try it out ;-) ).
> >Ewald
>
> Many thanks Ewald.
> I decided to use windows unit for Windows (it works so...).
> Sadly, for Linux, i do not find a solution...
> Many thanks.

For Linux you *must* use the name and not the ordinal and for Windows I'd advice you the same except the author of that DLL documents that the ordinals will stay the same between versions (but even then using the name is more portable).

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Sven Barth-2
In reply to this post by Sven Barth-2

Am 14.01.2014 09:24 schrieb "Sven Barth" <[hidden email]>:
> Maybe an overload could be added to load functions by ordinal on Windows and which simply returns Nil on other platforms.

I've now added an overload which is implemented for the Windows systems and returns Nil on other targets.

For Delphi compatibility we should maybe also add a PAnsiChar overload for GetProcAddress so that existing code could safely use "PAnsiChar(1)".

Regards,
Sven


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Michael Van Canneyt


On Tue, 14 Jan 2014, Sven Barth wrote:

>
> Am 14.01.2014 09:24 schrieb "Sven Barth" <[hidden email]>:
> > Maybe an overload could be added to load functions by ordinal on Windows and which simply returns Nil on other platforms.
>
> I've now added an overload which is implemented for the Windows systems and returns Nil on other targets.
>
> For Delphi compatibility we should maybe also add a PAnsiChar overload for GetProcAddress so that existing code could safely use
> "PAnsiChar(1)".

Definitely not. I don't think we should encourage this.

The dynlibs unit was intended and conceived as a clean,
cross-platform implementation of dynamic library loading.

It already contains several dubious constructs "for delphi compatibility",
I don't think we should add another one. I will not remove your addition,
but adding more is really out of the question.

Delphi compatibility in this case is utter nonsense,
since Delphi doesn't have a dynlibs unit to begin with.

There are limits to the amount of prostitution I am willing to tolerate.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs
In reply to this post by hinst

> I identified the problem........

Mr Hint : you are magic...
I cannot find words...
1.000 gigas of thanks ( even more...).

Of course you get a big credit in uos project.

Fred



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs
In reply to this post by Michael Van Canneyt
@ Hinst, Michael, Tomas, Mark, Lukasz, Ewald, Marco, Sven and Waldo :

MANY, MANY THANKS.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs
In reply to this post by Michael Van Canneyt
Hello.

Thanks to Mister Hinst, i was able to load and run, in Windows, with dynlib.pas, SoundTouch.dll. Perfect and re-thanks.

Now, i begin a other hard battle : load and run in Linux, libSoundTouch.so.

With the extremely helpful message of Mister Ewald :
> Try to find the names of the symbols defined in the shared object (nm comes to mind).

I run nm and find the name of the procedures ( PS : without nm-Ewald's tip, you must be a high soothsayer to find it)
For example, a C called procedure : soundtouch_getVersionString() becomes : _ZN10soundtouch10SoundTouch16getVersionStringEv() !!!

And, believe it or not... it works...

I have only a problem with one procedure:

This c procedure is declared as this :
SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int srate);

And i translate it like that :

soundtouch_setSampleRate : procedure(h : THandle; srate : cardinal); cdecl;
and for dynamic-loading :
Pointer(soundtouch_setSampleRate):= GetProcAddress(LibHandle, Pchar('_ZN10soundtouch10SoundTouch13setSampleRateEj'));

Sadly i get that message when i try to load that procedure :

An unhandled exception occurred at $00007F7D76D61AE8:
EAccessViolation: Access violation $00007F7D76D61AE8
(program exited with code: 217)

Does somebody have some light for this ?

Many thanks.


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

Ludo Brands
On 01/17/2014 03:16 PM, Fred van Stappen wrote:

>
> I run nm and find the name of the procedures ( PS : without nm-Ewald's tip, you must be a high soothsayer to find it)
> For example, a C called procedure : soundtouch_getVersionString() becomes : _ZN10soundtouch10SoundTouch16getVersionStringEv() !!!
>

The _ZN10soundtouch10SoundTouch16getVersionStringEv name mangling
suggests that this is a C++ lib, not a C lib. Generally speaking, you
can't call C++ libs from fpc.

Ludo

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: windows.GetProcAddress() vs DynLibs.GetProcAddress()

fredvs

> > I run nm and find the name of the procedures ( PS : without nm-Ewald's tip, you must be a high soothsayer to find it)
> > For example, a C called procedure : soundtouch_getVersionString() becomes : _ZN10soundtouch10SoundTouch16getVersionStringEv() !!!
> >
>
> The _ZN10soundtouch10SoundTouch16getVersionStringEv name mangling
> suggests that this is a C++ lib, not a C lib. Generally speaking, you
> can't call C++ libs from fpc.
>
> Ludo

Yep, Ludo, many thanks to take care but...

I have a test program who use some procedures to test , for example :

 FVersionID := soundtouch_getVersionId();
 FVersionString := StrPas(soundtouch_getVersionString());  
 
  writeln(FVersionID);
  writeln(FVersionString);

>>> Result :

> 10800
> 1.8.0

So, it seems to work...

Those procedures are declared as this :

Pointer(soundtouch_getVersionId)    := GetProcAddress(LibHandle, Pchar('_ZN10soundtouch10SoundTouch12getVersionIdEv')); 
 
Pointer(soundtouch_getVersionString):= GetProcAddress(LibHandle,Pchar('_ZN10soundtouch10SoundTouch16getVersionStringEv')); 

I only have problem with :
_ZN10soundtouch10SoundTouch16getVersionStringEv()...


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
123