Sign in Join

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

Mailing lists / fpc-pascal / 2014-01

windows.GetProcAddress() vs DynLibs.GetProcAddress()

60 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

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

Fred van Stappen

Hello.

I have a external dll. In Windows i can access perfectly the procedures with GetProcAddress() if i use Windows unit.

If i use DynLibs unit, prog crash when i try to load the procedure. I prefer to use DynLibs unit because i want to use the dll for Linux too (of course with library.so).

I have try, in linux to access the procedure with DynLibs too but same crash than for Windows. What must i do to access procedure with DynLibs ?

Many thanks.

Michael Van Canneyt
to Fred van Stappen
Fred van Stappen wrote 10 lines
Hello. I have a external dll. In Windows i can access perfectly the procedures with GetProcAddress() if i use Windows unit. If i use DynLibs unit, prog crash when i try to load the procedure. I prefer to use DynLibs unit because i want to use the dll for Linux too (of course with library.so). I have try, in linux to access the procedure with DynLibs too but same crash than for Windows. What must i do to access procedure with DynLibs ?

Can you be more specific ? What error do you get ? Can show some code ?

Michael.

Tomas Hajny
to Fred van Stappen: Hello. I have a external dll. In Windows i can access perfectly the procedures with…
Fred van Stappen wrote 13 lines
Hello. I have a external dll. In Windows i can access perfectly the procedures with GetProcAddress() if i use Windows unit. If i use DynLibs unit, prog crash when i try to load the procedure. I prefer to use DynLibs unit because i want to use the dll for Linux too (of course with library.so). I have try, in linux to access the procedure with DynLibs too but same crash than for Windows. What must i do to access procedure with DynLibs ?

Can you provide a simplified program demonstrating the problem? Does it "crash" when trying the obtain the address, or when trying to use it (e.g. after assignment to a procedural variable)? If it is the latter, have you checked that the calling conventions of your DLL and your procedural type match? If it is the former, how is the "crash" demonstrated (i.e. what happens)?

Tomas

Fred van Stappen
to Michael Van Canneyt: Can you be more specific ? What error do you get ? Can show some code ? Michael.
Show quoted text 23 lines
Date: Mon, 13 Jan 2014 11:58:21 +0100 From: To: Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() On Mon, 13 Jan 2014, Fred van Stappen wrote: > Hello. > > I have a external dll. In Windows i can access perfectly the procedures with > GetProcAddress() if i use Windows unit. > > If i use DynLibs unit, prog crash when i try to load the procedure. > I prefer to use DynLibs unit because i want to use the dll for Linux too (of course with library.so). > > I have try, in linux to access the procedure with DynLibs too but same crash than for Windows. > What must i do to access procedure with DynLibs ? Can you be more specific ? What error do you get ? Can show some code ? Michael.

Hello and many thanks for answer.

The library is SoundTouch.dll and libSoundTouch.so from :

> http://www.surina.net/soundtouch/ >>Here part of working code (if i call soundtouch_createInstance, it works)

...
uses
Windows ;
...

var
soundtouch_createInstance : function() : THandle; stdcall;

...

procedure InitLib(LibFile : PAnsiChar);
begin
  LibHandle := LoadLibrary(LibFile);
  if LibHandle  0 then
     Pointer(soundtouch_createInstance)   := GetProcAddress(LibHandle, PAnsiChar('soundtouch_createInstance'));
/////////////////////
>> Here part of NOT working code (if i call soundtouch_createInstance, it crash)

...
uses
dynlibs ;
...

var
soundtouch_createInstance : function() : THandle; stdcall;

...

procedure InitLib(LibFile : PAnsiChar);
begin
LibHandle:=DynLibs.LoadLibrary(libfilename);
  if LibHandle  DynLibs.NilHandle then
    Pointer(soundtouch_createInstance)        := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance'));
/////////////////////

Many thanks.

Michael Van Canneyt
to Fred van Stappen
Fred van Stappen wrote 18 lines
>>> Here part of NOT working code (if i call soundtouch_createInstance, it crash) ... uses   dynlibs ; ... var soundtouch_createInstance : function() : THandle; stdcall;  ... procedure InitLib(LibFile : PAnsiChar); begin LibHandle:=DynLibs.LoadLibrary(libfilename);   if LibHandle DynLibs.NilHandle then         Pointer(soundtouch_createInstance)        := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance'));

Remove the typecast PansiChar()

Michael.

Fred van Stappen
to Tomas Hajny: Can you provide a simplified program demonstrating the problem? Does it "crash" when…
Show quoted text 28 lines
Date: Mon, 13 Jan 2014 12:07:54 +0100 From: To: Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() On Mon, January 13, 2014 11:47, Fred van Stappen wrote: > Hello. > > I have a external dll. In Windows i can access perfectly the procedures > with > GetProcAddress() if i use Windows unit. > > If i use DynLibs unit, prog crash when i try to load the procedure. > I prefer to use DynLibs unit because i want to use the dll for Linux too > (of course with library.so). > > I have try, in linux to access the procedure with DynLibs too but same > crash than for Windows. > What must i do to access procedure with DynLibs ? Can you provide a simplified program demonstrating the problem? Does it "crash" when trying the obtain the address, or when trying to use it (e.g. after assignment to a procedural variable)? If it is the latter, have you checked that the calling conventions of your DLL and your procedural type match? If it is the former, how is the "crash" demonstrated (i.e. what happens)? Tomas

Hello Tomas.

I have sent part of code in earlier topic, do you need more ? The crash append when i try to call the procedure.

LoadLibrary(libfile) seems to work, i get result as "true".

Thanks

Mark Morgan Lloyd
to Tomas Hajny: Can you provide a simplified program demonstrating the problem? Does it "crash" when…
Tomas Hajny wrote 21 lines
On Mon, January 13, 2014 11:47, Fred van Stappen wrote: > Hello. > > I have a external dll. In Windows i can access perfectly the procedures > with > GetProcAddress() if i use Windows unit. > > If i use DynLibs unit, prog crash when i try to load the procedure. > I prefer to use DynLibs unit because i want to use the dll for Linux too > (of course with library.so). > > I have try, in linux to access the procedure with DynLibs too but same > crash than for Windows. > What must i do to access procedure with DynLibs ? Can you provide a simplified program demonstrating the problem? Does it "crash" when trying the obtain the address, or when trying to use it (e.g. after assignment to a procedural variable)? If it is the latter, have you checked that the calling conventions of your DLL and your procedural type match? If it is the former, how is the "crash" demonstrated (i.e. what happens)?

Also note the availability of GetLoadErrorStr on most platforms in later versions of the RTL (>= 2.6.2 I think).

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Fred van Stappen
to Michael Van Canneyt: Remove the typecast PansiChar() Michael.

Date: Mon, 13 Jan 2014 12:32:53 +0100
From:
To:
Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress()

Fred van Stappen wrote 18 lines
>>> Here part of NOT working code (if i call soundtouch_createInstance, it crash) ... uses dynlibs ; ... var soundtouch_createInstance : function() : THandle; stdcall; ... procedure InitLib(LibFile : PAnsiChar); begin LibHandle:=DynLibs.LoadLibrary(libfilename); if LibHandle DynLibs.NilHandle then Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance'));

Remove the typecast PansiChar()

Michael.

> Hello Michael and thanks for answer.

But if i remove PansiChar(), i still get :

An unhandled exception occurred at $0000000000000000: EAccessViolation: Access violation
$0000000000000000

Michael Van Canneyt
to Fred van Stappen
Fred van Stappen wrote 36 lines
Date: Mon, 13 Jan 2014 12:32:53 +0100 From: To: Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() On Mon, 13 Jan 2014, Fred van Stappen wrote: > > >>> Here part of NOT working code (if i call soundtouch_createInstance, it crash) > ... > uses   > dynlibs ; > ... > > var > soundtouch_createInstance : function() : THandle; stdcall;  > > ... > > procedure InitLib(LibFile : PAnsiChar); > begin > LibHandle:=DynLibs.LoadLibrary(libfilename); >   if LibHandle DynLibs.NilHandle then >     >     Pointer(soundtouch_createInstance)        := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); Remove the typecast PansiChar() Michael. >> Hello Michael and thanks for answer. But if i remove PansiChar(), i still get : An unhandled exception occurred at $0000000000000000: EAccessViolation: Access violation $0000000000000000

What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ?

Michael.

Fred van Stappen
to Michael Van Canneyt
Fred van Stappen wrote 36 lines
Date: Mon, 13 Jan 2014 12:32:53 +0100 From: To: Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() On Mon, 13 Jan 2014, Fred van Stappen wrote: > > >>> Here part of NOT working code (if i call soundtouch_createInstance, it crash) > ... > uses > dynlibs ; > ... > > var > soundtouch_createInstance : function() : THandle; stdcall; > > ... > > procedure InitLib(LibFile : PAnsiChar); > begin > LibHandle:=DynLibs.LoadLibrary(libfilename); > if LibHandle DynLibs.NilHandle then > > Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); Remove the typecast PansiChar() Michael. >> Hello Michael and thanks for answer. But if i remove PansiChar(), i still get : An unhandled exception occurred at $0000000000000000: EAccessViolation: Access violation $0000000000000000

What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ?

Michael.
Thanks for answer Michael.

Hum, how can i get the value of pointer if the application crash when i do :

> FHandle := soundtouch_createInstance();

Maybe, i dont understood your question...

Michael Van Canneyt
to Fred van Stappen
Fred van Stappen wrote 24 lines
> > begin > > LibHandle:=DynLibs.LoadLibrary(libfilename); > >   if LibHandle DynLibs.NilHandle then > >     > >     Pointer(soundtouch_createInstance)        := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance ')); > > Remove the typecast PansiChar() > > Michael. > >> Hello Michael and thanks for answer. > But if i remove PansiChar(), i still get : > An unhandled exception occurred at $0000000000000000: > EAccessViolation: Access violation > $0000000000000000 What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? Michael. Thanks for answer Michael. Hum, how can i get the value of pointer if the application crash when i do : >>  FHandle := soundtouch_createInstance();  

Do a

Writeln((@soundtouch_createInstance)=Nil);

Michael.

Lukasz Sokol
to Fred van Stappen: What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is…

Hi,

'scue me if I did not catch something, but

On 13/01/14 12:13, Fred van Stappen wrote:
[...]

Show quoted text 7 lines
> > procedure InitLib(LibFile : PAnsiChar); > > begin > > LibHandle:=DynLibs.LoadLibrary(libfilename); > > if LibHandle DynLibs.NilHandle then > > > > Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); >
/// why not just :
@soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance'));

(or without the PAnsiChar cast as Michael said:)

@soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, 'soundtouch_createInstance');

?

> Remove the typecast PansiChar() > > Michael.

[...]

Show quoted text 13 lines
What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? Michael. Thanks for answer Michael. Hum, how can i get the value of pointer if the application crash when i do : >> FHandle := soundtouch_createInstance(); Maybe, i dont understood your question...
if Assigned(soundtouch_createInstance) then ShowMessage('Got good pointer for soundtouch_createInstance')
else ShowMessage('soundtouch_createInstance not assigned);

placed directly after the GetProcedureAddress call ?

Fred van Stappen
to Michael Van Canneyt: Do a Writeln((@soundtouch_createInstance)=Nil); Michael.
Fred van Stappen wrote 24 lines
> > begin > > LibHandle:=DynLibs.LoadLibrary(libfilename); > > if LibHandle DynLibs.NilHandle then > > > > Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance ')); > > Remove the typecast PansiChar() > > Michael. > >> Hello Michael and thanks for answer. > But if i remove PansiChar(), i still get : > An unhandled exception occurred at $0000000000000000: > EAccessViolation: Access violation > $0000000000000000 What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? Michael. Thanks for answer Michael. Hum, how can i get the value of pointer if the application crash when i do : >> FHandle := soundtouch_createInstance();

Do a

Writeln((@soundtouch_createInstance)=Nil);

Michael.
___________

Thanks Michael.

Result in Linux for :

if ST_Load('/home/fred/libSoundTouch/libSoundTouch.so')
  then   writeln('ok') else  writeln('no') ;
> ok
Writeln((@soundtouch_createInstance)=Nil);
> FALSE

I agree it is very strange, in windows, with unit Windows, it works perfectly..

Michael Van Canneyt
to Fred van Stappen
Fred van Stappen wrote 44 lines
On Mon, 13 Jan 2014, Fred van Stappen wrote: > > > begin > > > LibHandle:=DynLibs.LoadLibrary(libfilename); > > >   if LibHandle DynLibs.NilHandle then > > >     > > >     Pointer(soundtouch_createInstance)        := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstan ce > ')); > > > > Remove the typecast PansiChar() > > > > Michael. > > >> Hello Michael and thanks for answer. > > But if i remove PansiChar(), i still get : > > An unhandled exception occurred at $0000000000000000: > > EAccessViolation: Access violation > > $0000000000000000 > > What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? > > Michael. > Thanks for answer Michael. > > Hum, how can i get the value of pointer if the application crash when i do : > > >>  FHandle := soundtouch_createInstance();   Do a Writeln((@soundtouch_createInstance)=Nil); Michael. ___________ Thanks Michael. Result in Linux for : if ST_Load('/home/fred/libSoundTouch/libSoundTouch.so') then writeln('ok') else writeln('no') ; >> ok Writeln((@soundtouch_createInstance)=Nil); >> FALSE I agree it is very strange, in windows, with unit Windows, it works perfectly..

Wait.

What happens if you use dynlibs on windows ?

Because there can be 1000 other reasons why the load failed on linux, not necessarily connected to dynlibs.

Michael.

Fred van Stappen
to Michael Van Canneyt
Fred van Stappen wrote 44 lines
On Mon, 13 Jan 2014, Fred van Stappen wrote: > > > begin > > > LibHandle:=DynLibs.LoadLibrary(libfilename); > > > if LibHandle DynLibs.NilHandle then > > > > > > Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstan ce > ')); > > > > Remove the typecast PansiChar() > > > > Michael. > > >> Hello Michael and thanks for answer. > > But if i remove PansiChar(), i still get : > > An unhandled exception occurred at $0000000000000000: > > EAccessViolation: Access violation > > $0000000000000000 > > What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? > > Michael. > Thanks for answer Michael. > > Hum, how can i get the value of pointer if the application crash when i do : > > >> FHandle := soundtouch_createInstance(); Do a Writeln((@soundtouch_createInstance)=Nil); Michael. ___________ Thanks Michael. Result in Linux for : if ST_Load('/home/fred/libSoundTouch/libSoundTouch.so') then writeln('ok') else writeln('no') ; >> ok Writeln((@soundtouch_createInstance)=Nil); >> FALSE I agree it is very strange, in windows, with unit Windows, it works perfectly..

Wait.

What happens if you use dynlibs on windows ?

Because there can be 1000 other reasons why the load failed on linux, not necessarily connected to dynlibs.

Michael.
____________________________________________

Yep, Michael, many thanks for helping.

> What happens if you use dynlibs on windows ?

Exactly the same as for Linux, it crash.

What i do not understand it is why, with Windows unit, it works perfectly and with Dynlibs unit, it crash. (with same code, of course).

Fred van Stappen
to Lukasz Sokol: 'scue me if I did not catch something, but [...] /// why not just :…
Show quoted text 52 lines
To: From: Date: Mon, 13 Jan 2014 12:52:51 +0000 Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() Hi, 'scue me if I did not catch something, but On 13/01/14 12:13, Fred van Stappen wrote: [...] >> > procedure InitLib(LibFile : PAnsiChar); >> > begin >> > LibHandle:=DynLibs.LoadLibrary(libfilename); >> > if LibHandle DynLibs.NilHandle then >> > >> > Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); >> /// why not just : @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); (or without the PAnsiChar cast as Michael said:) @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, 'soundtouch_createInstance'); ? >> Remove the typecast PansiChar() >> >> Michael. [...] > > What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? > > Michael. > > Thanks for answer Michael. > > Hum, how can i get the value of pointer if the application crash when i do : > >>> FHandle := soundtouch_createInstance(); > > Maybe, i dont understood your question... > if Assigned(soundtouch_createInstance) then ShowMessage('Got good pointer for soundtouch_createInstance') else ShowMessage('soundtouch_createInstance not assigned); placed directly after the GetProcedureAddress call ?

_______________________________

Show quoted text 8 lines
/// why not just : @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); (or without the PAnsiChar cast as Michael said:) @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, 'soundtouch_createInstance');

Many thanks... but im in a web-cafe and they want to close, i have to go...

I will try this and give you news later.

Many thanks.

Fred van Stappen
to Lukasz Sokol: 'scue me if I did not catch something, but [...] /// why not just :…
Show quoted text 52 lines
To: From: Date: Mon, 13 Jan 2014 12:52:51 +0000 Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() Hi, 'scue me if I did not catch something, but On 13/01/14 12:13, Fred van Stappen wrote: [...] >> > procedure InitLib(LibFile : PAnsiChar); >> > begin >> > LibHandle:=DynLibs.LoadLibrary(libfilename); >> > if LibHandle DynLibs.NilHandle then >> > >> > Pointer(soundtouch_createInstance) := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); >> /// why not just : @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); (or without the PAnsiChar cast as Michael said:) @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, 'soundtouch_createInstance'); ? >> Remove the typecast PansiChar() >> >> Michael. [...] > > What is the value of Pointer(soundtouch_createInstance) after the above statement ? Is it nil ? > > Michael. > > Thanks for answer Michael. > > Hum, how can i get the value of pointer if the application crash when i do : > >>> FHandle := soundtouch_createInstance(); > > Maybe, i dont understood your question... > if Assigned(soundtouch_createInstance) then ShowMessage('Got good pointer for soundtouch_createInstance') else ShowMessage('soundtouch_createInstance not assigned); placed directly after the GetProcedureAddress call ?

___________

Hello Lucaz

 /// why not just :
@soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance'));

Get that error :

> libSoundTouch.pas(56,5) Error: Can't assign values to an address
Lukasz Sokol
to Fred van Stappen

On 13/01/14 13:36, Fred van Stappen wrote:
[...]

Show quoted text 11 lines
Hello Lucaz /// why not just : > > @soundtouch_createInstance := DynLibs.GetProcedureAddress(LibHandle, PAnsiChar('soundtouch_createInstance')); > Get that error : >> libSoundTouch.pas(56,5) Error: Can't assign values to an address

This (@syntax) is in (OBJ)FPC mode, your example is Delphi mode.

http://wiki.freepascal.org/Lazarus/FPC_Libraries#Loadlibrary_-_dynamically_loading_a_dynamic_library

http://forum.lazarus.freepascal.org/index.php?topic=1148.0

OK I stand corrected, re. the pointer() cast...

but then why not declare in a public header for this wrapper:
type
  TSoundtouchCreateInstanceProc = procedure;
then
soundtouch_createinstance := TSoundtouchCreateInstanceProc(DynLibs.GetProcedureAddress(...));

(nb. delphi mode)

?

-L.

Fred van Stappen
to Lukasz Sokol

Hello and many thanks to help.

Here demo to show the problem (i hope).

There is a program : test.pas
It uses a external library soundtouch_2.dll.

There are 2 wrappers :
soundtouch_windows.pas (who uses windows unit) and soundtouch_dynlib.pas (who uses dynlib unit)

There are also 4 binaries :

test_windows_fpc262.exe => OK, works (use soundtouch_windows.pas and compiled with fpc 262)

test_windows_fpc271.exe => NO, does NOT work (use soundtouch_windows.pas and compiled with fpc 271)

test_dynlib_fpc262.exe => NO, does NOT work (use soundtouch_dynlib.pas and compiled with fpc 262)

test_windows_fpc271.exe => NO, does NOT work (use soundtouch_windows.pas and compiled with fpc 271)

You may test the prog with soundtouch_windows.pas or soundtouch_dynlib.pas (uncomment the one you want in use section).

Many thanks.

Fred van Stappen
to Fred van Stappen

From:
To:
Date: Mon, 13 Jan 2014 17:33:47 +0100
Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress()

Hello and many thanks to help.

Here demo to show the problem (i hope).

There is a program : test.pas
It uses a external library soundtouch_2.dll.

There are 2 wrappers :
soundtouch_windows.pas (who uses windows unit) and soundtouch_dynlib.pas (who uses dynlib unit)

There are also 4 binaries :

test_windows_fpc262.exe => OK, works (use soundtouch_windows.pas and compiled with fpc 262)

test_windows_fpc271.exe => NO, does NOT work (use soundtouch_windows.pas and compiled with fpc 271)

test_dynlib_fpc262.exe => NO, does NOT work (use soundtouch_dynlib.pas and compiled with fpc 262)

test_windows_fpc271.exe => NO, does NOT work (use soundtouch_windows.pas and compiled with fpc 271)

You may test the prog with soundtouch_windows.pas or soundtouch_dynlib.pas (uncomment the one you want in use section).

Many thanks.

Ewald
to Fred van Stappen: Hello and many thanks to help. Here demo to show the problem (i hope). There is a program…
Fred van Stappen wrote 5 lines
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
Fred van Stappen
to Ewald

From:
Date: Mon, 13 Jan 2014 21:25:27 +0100
To:
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).

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

Ewald
to Fred van Stappen
Fred van Stappen wrote 8 lines
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
waldo kitty
to Fred van Stappen: From: Date: Mon, 13 Jan 2014 21:25:27 +0100 To: Subject: Re: [fpc-pascal]…

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.
Sven Barth
to Ewald: That explains why it works in windows probably, there you can specify an index to go with…
"Ewald" wrote 14 lines
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.

Show quoted text 7 lines
> >> 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

Marco van de Voort
to Sven Barth

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?

Sven Barth
to Marco van de Voort
"Marco van de Voort" wrote 8 lines
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

Fred van Stappen
to Ewald: That explains why it works in windows probably, there you can specify an index to go with…
Show quoted text 5 lines
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.

Fred van Stappen
to waldo kitty: fred, can you please adjust your quoting to use the standard '>' for previous responses…
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

hinst
to Fred van Stappen: Many thanks Ewald. I decided to use windows unit for Windows (it works so...). Sadly, for…

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

Show quoted text 15 lines
>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  -   http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Tomas Hajny
to Sven Barth: index to go with your exported procedures IIRC. I don't know if this is possible though…
Sven Barth wrote
Am 14.01.2014 00:12 schrieb "Ewald" : > 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).

Show quoted text 6 lines
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

Sven Barth
to Tomas Hajny
"Tomas Hajny" wrote 23 lines
On Tue, January 14, 2014 09:24, Sven Barth wrote: > Am 14.01.2014 00:12 schrieb "Ewald" : >> 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

Sven Barth
to Fred van Stappen: Many thanks Ewald. I decided to use windows unit for Windows (it works so...). Sadly, for…
"Fred van Stappen" wrote
>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

Show quoted text 7 lines
> (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

Sven Barth
to Sven Barth: index to go with your exported procedures IIRC. I don't know if this is possible though…
"Sven Barth" wrote
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

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 8 lines
Am 14.01.2014 09:24 schrieb "Sven Barth" : > 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.

Fred van Stappen
to Michael Van Canneyt: Definitely not. I don't think we should encourage this. The dynlibs unit was intended and…

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.

Ludo Brands
to Fred van Stappen
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

Fred van Stappen
to Ludo Brands
Show quoted text 9 lines
> 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()...

Fred van Stappen
to Fred van Stappen
I only have problem with : _ZN10soundtouch10SoundTouch16getVersionStringEv()...

Ooops, have to read :

I only have problem with :
Pointer(soundtouch_setSampleRate):= GetProcAddress(LibHandle, Pchar('_ZN10soundtouch10SoundTouch13setSampleRateEj'));
Marco van de Voort
to Fred van Stappen: Hello. Thanks to Mister Hinst, i was able to load and run, in Windows, with dynlib.pas,…

In our previous episode, Fred van Stappen said:

Show quoted text 12 lines
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 :

Handle is not defined on Linux. Many libraries emulate some handle type, but it depends on the vendor if they make handle 32-bit or 64-bit.

Make sure that sizeof(HANDLE) in C++ matches sizeof(THandle) in FPC. Adjust the type you use at the FPC side if necessary.

Fred van Stappen
to Marco van de Voort
Show quoted text 21 lines
Subject: Re: [fpc-pascal] windows.GetProcAddress() vs DynLibs.GetProcAddress() In our previous episode, Fred van Stappen said: > 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 : Handle is not defined on Linux. Many libraries emulate some handle type, but it depends on the vendor if they make handle 32-bit or 64-bit. Make sure that sizeof(HANDLE) in C++ matches sizeof(THandle) in FPC. Adjust the type you use at the FPC side if necessary.

Yep, Marco, many thanks...

Hum, :

Make sure that sizeof(HANDLE) in C++ matches sizeof(THandle) in FPC. Adjust the type you use at the FPC side if necessary.

How to do that ? (sorry, i do not understand)

Ludo Brands
to Fred van Stappen: Yep, Ludo, many thanks to take care but... I have a test program who use some procedures…
Fred van Stappen wrote 39 lines
> > 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'));

That are functions without any parameters that seemingly don't do a lot. Do you have any function working that takes a handle as a parameter? What is the value of the handle that was returned?

Ludo

Fred van Stappen
to Ludo Brands
Show quoted text 43 lines
On 01/17/2014 03:55 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 > > 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')); > > That are functions without any parameters that seemingly don't do a lot. Do you have any function working that takes a handle as a parameter? What is the value of the handle that was returned?

Yep Ludo, thanks to answer and...

Indeed, all the functions without any parameters are working.

And all the other must be initialized with  Soundtouch_setSampleRate(FHandle, samrate);

And, because it does not work, i cannot try the other procedures...

PS : FHandle := soundtouch_createInstance();
Seems to work (i do not get error message)
and this one works too :
soundtouch_setChannels(FHandle, 2);
but this no :
soundtouch_setSampleRate(FHandle, 44100);

And without to set sample-rate, all other procedures are not working...

Many thanks

Fred van Stappen
to Ludo Brands: That are functions without any parameters that seemingly don't do a lot. Do you have any…
What is the value of the handle that was returned? Ludo

Re-hello Ludo.

That code :

if ST_Load('/home/fred/dynlib_vs_windows/libSoundTouch.so') then
   writeln('libSoundTouch.so loaded');
 if FHandle  NilHandle then soundtouch_clear(FHandle);
 FHandle := soundtouch_createInstance();
  writeln(FHandle);
 FVersionID := soundtouch_getVersionId();
  writeln(FVersionID);
 FVersionString := StrPas(soundtouch_getVersionString());
  writeln(FVersionString);
 soundtouch_setChannels(FHandle, 2);
 writeln('OK SetChannels');
 soundtouch_setSampleRate(FHandle, 44100);
 writeln('OK SampleRate');
Gives that result :

libSoundTouch.so loaded
22351184
10800
1.8.0
OK SetChannels
An unhandled exception occurred at $00007FE493CE2AE8: EAccessViolation: Access violation
$00007FE493CE2AE8
------------------
(program exited with code: 217)

Marco van de Voort
to Fred van Stappen: Yep, Marco, many thanks... Hum, : How to do that ? (sorry, i do not understand)

In our previous episode, Fred van Stappen said:

Show quoted text 14 lines
> Handle is not defined on Linux. Many libraries emulate some handle type, but > it depends on the vendor if they make handle 32-bit or 64-bit. > > Make sure that sizeof(HANDLE) in C++ matches sizeof(THandle) in FPC. Adjust > the type you use at the FPC side if necessary. Yep, Marco, many thanks... Hum, : > Make sure that sizeof(HANDLE) in C++ matches sizeof(THandle) in FPC. >Adjust the type you use at the FPC side if necessary. How to do that ? (sorry, i do not understand)
Writeln(sizeof(THandle)); // for console apps
somememo.lines.add(sizeof(THandle)); // for gui apps.

I don't know if the Handle type in the header is defined by the C++ compiler or by the package itself. Consult their respective documentation for more info.

Fred van Stappen
to Marco van de Voort
Writeln(sizeof(THandle)); // for console apps
FHandle := soundtouch_createInstance();
writeln(FHandle);
Writeln(sizeof(FHandle));

Gives that result :

10321232
4

I don't know if the Handle type in the header is defined by the C++ compiler or by the package itself. Consult their respective documentation for more info.

?

Ludo Brands
to Fred van Stappen
Fred van Stappen wrote 13 lines
> I don't know if the Handle type in the header is defined by the C++ compiler > or by the package itself. Consult their respective documentation for more > info. Here declaration of create instance : // Create a new instance of SoundTouch processor. SOUNDTOUCHDLL_API HANDLE __cdecl soundtouch_createInstance();

That routine is defined in SoundTouchDLL.cpp which is the windows dll wrapper. Do you have the linux equivalent?

Ludo

Ewald
to Ludo Brands
Ludo Brands wrote 17 lines
On 01/17/2014 05:09 PM, Fred van Stappen wrote: > >> I don't know if the Handle type in the header is defined by the C++ > compiler >> or by the package itself. Consult their respective documentation for more >> info. > > Here declaration of create instance : > > // Create a new instance of SoundTouch processor. > SOUNDTOUCHDLL_API HANDLE __cdecl soundtouch_createInstance(); > > > That routine is defined in SoundTouchDLL.cpp which is the windows dll wrapper.

Note one detail: it is declared there as __stdcall, not as __cdecl, so perhaps this has something to do with it?

@Fred: Also note that the type HANDLE is defined there as a pointer, so [as a sanity test of sorts] sizeof(Handle {in pascal}) should be equal to sizeof(HANDLE /*in C/C++*/).

Ewald
Fred van Stappen
to Ludo Brands: That routine is defined in SoundTouchDLL.cpp which is the windows dll wrapper. Do you…
That routine is defined in SoundTouchDLL.cpp which is the windows dll wrapper. Do you have the linux equivalent? Ludo

PS : For new new arriving : SoundTouchDLL.cpp is part of SoundTouch, a audio processing library :

@ Ludo :

In /source/SoundTouch/ there is SoundTouch.cpp

I have compiled the package in Linux like said in readme with : ./bootstrap" script, then configure, make all, sudo make install. And i get a libSoundTouch.so in usr/local/lib.

Fred van Stappen
to Ewald: Note one detail: it is declared there as __stdcall, not as __cdecl, so perhaps this has…
Show quoted text 6 lines
Note one detail: it is declared there as __stdcall, not as __cdecl, so perhaps this has something to do with it? @Fred: Also note that the type HANDLE is defined there as a pointer, so [as a sanity test of sorts] sizeof(Handle {in pascal}) should be equal to sizeof(HANDLE /*in C/C++*/). -- Ewald

Yep, there is a brand new wrapper from trunk :

//////////////////////////////////////////////////////////////////////////////
///
/// SoundTouch DLL wrapper - wraps SoundTouch routines into a Dynamic Load
/// Library interface.
///
/// Author        : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// $Id: SoundTouchDLL.h 94 2010-12-12 18:28:49Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
//  SoundTouch audio processing library
//  Copyright (c) Olli Parviainen
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
////////////////////////////////////////////////////////////////////////////////

#ifndef _SoundTouchDLL_h_
#define _SoundTouchDLL_h_

#ifdef __cplusplus

#ifdef DLL_EXPORTS
#define SOUNDTOUCHDLL_API extern "C" __declspec(dllexport) #else
#define SOUNDTOUCHDLL_API extern "C" __declspec(dllimport) #endif

#else

#ifdef DLL_EXPORTS
#define SOUNDTOUCHDLL_API __declspec(dllexport)
#else
#define SOUNDTOUCHDLL_API __declspec(dllimport)
#endif

#endif // __cplusplus

typedef void * HANDLE;
/// Create a new instance of SoundTouch processor.
SOUNDTOUCHDLL_API HANDLE __cdecl soundtouch_createInstance();
/// Destroys a SoundTouch processor instance.
SOUNDTOUCHDLL_API void __cdecl soundtouch_destroyInstance(HANDLE h);
/// Get SoundTouch library version string
SOUNDTOUCHDLL_API const char *__cdecl soundtouch_getVersionString();
/// Get SoundTouch library version string - alternative function for
/// environments that can't properly handle character string as return value
SOUNDTOUCHDLL_API void __cdecl soundtouch_getVersionString2(char* versionString, int bufferSize);
/// Get SoundTouch library version Id
SOUNDTOUCHDLL_API unsigned int __cdecl soundtouch_getVersionId();
/// Sets new rate control value. Normal rate = 1.0, smaller values
/// represent slower rate, larger faster rates.
SOUNDTOUCHDLL_API void __cdecl soundtouch_setRate(HANDLE h, float newRate);
/// Sets new tempo control value. Normal tempo = 1.0, smaller values
/// represent slower tempo, larger faster tempo.
SOUNDTOUCHDLL_API void __cdecl soundtouch_setTempo(HANDLE h, float newTempo);
/// Sets new rate control value as a difference in percents compared
/// to the original rate (-50 .. +100 %);
SOUNDTOUCHDLL_API void __cdecl soundtouch_setRateChange(HANDLE h, float newRate);
/// Sets new tempo control value as a difference in percents compared
/// to the original tempo (-50 .. +100 %);
SOUNDTOUCHDLL_API void __cdecl soundtouch_setTempoChange(HANDLE h, float newTempo);
/// Sets new pitch control value. Original pitch = 1.0, smaller values
/// represent lower pitches, larger values higher pitch.
SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitch(HANDLE h, float newPitch);
/// Sets pitch change in octaves compared to the original pitch
/// (-1.00 .. +1.00);
SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitchOctaves(HANDLE h, float newPitch);
/// Sets pitch change in semi-tones compared to the original pitch
/// (-12 .. +12);
SOUNDTOUCHDLL_API void __cdecl soundtouch_setPitchSemiTones(HANDLE h, float newPitch);
/// Sets the number of channels, 1 = mono, 2 = stereo
SOUNDTOUCHDLL_API void __cdecl soundtouch_setChannels(HANDLE h, unsigned int numChannels);
/// Sets sample rate.
SOUNDTOUCHDLL_API void __cdecl soundtouch_setSampleRate(HANDLE h, unsigned int srate);
/// Flushes the last samples from the processing pipeline to the output.
/// Clears also the internal processing buffers.
//
/// Note: This function is meant for extracting the last samples of a sound
/// stream. This function may introduce additional blank samples in the end
/// of the sound stream, and thus it's not recommended to call this function
/// in the middle of a sound stream.
SOUNDTOUCHDLL_API void __cdecl soundtouch_flush(HANDLE h);
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
/// the input of the object. Notice that sample rate _has_to_ be set before
/// calling this function, otherwise throws a runtime_error exception.
SOUNDTOUCHDLL_API void __cdecl soundtouch_putSamples(HANDLE h,
        const float *samples,       ///< Pointer to sample buffer.
        unsigned int numSamples     ///< Number of samples in buffer. Notice
                                    ///< that in case of stereo-sound a single sample
                                    ///< contains data for both channels.
        );
/// Clears all the samples in the object's output and internal processing
/// buffers.
SOUNDTOUCHDLL_API void __cdecl soundtouch_clear(HANDLE h);
/// Changes a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's.
///
/// \return 'TRUE' if the setting was succesfully changed
SOUNDTOUCHDLL_API BOOL __cdecl soundtouch_setSetting(HANDLE h,
                int settingId,   ///< Setting ID number. see SETTING_... defines.
                int value        ///< New setting value.
                );
/// Reads a setting controlling the processing system behaviour. See the
/// 'SETTING_...' defines for available setting ID's.
///
/// \return the setting value.
SOUNDTOUCHDLL_API int __cdecl soundtouch_getSetting(HANDLE h,
                          int settingId    ///< Setting ID number, see SETTING_... defines.
                );
/// Returns number of samples currently unprocessed.
SOUNDTOUCHDLL_API unsigned int __cdecl soundtouch_numUnprocessedSamples(HANDLE h);
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
/// sample buffer without copying them anywhere.
///
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
/// with 'ptrBegin' function.
SOUNDTOUCHDLL_API unsigned int __cdecl soundtouch_receiveSamples(HANDLE h,
            float *outBuffer,           ///< Buffer where to copy output samples.
            unsigned int maxSamples     ///< How many samples to receive at max.
            );
/// Returns number of samples currently available.
SOUNDTOUCHDLL_API unsigned int __cdecl soundtouch_numSamples(HANDLE h);
/// Returns nonzero if there aren't any samples available for outputting.
SOUNDTOUCHDLL_API int __cdecl soundtouch_isEmpty(HANDLE h);

#endif // _SoundTouchDLL_h_

Ewald
to Fred van Stappen
Fred van Stappen wrote
Yep, there is a brand new wrapper from trunk :

Ha, then you use/compiled a different version. Since a `extern "C"` preserves the symbol name (that is the trick I use to link in a lot of external C++ code: just put extern "C" in front of the symbol). or it could be that I am completely missing something here. [for example: is the symbol `DLL_EXPORTS` defined at compile time?]

Ewald
Fred van Stappen
to Ewald: Ha, then you use/compiled a different version. Since a `extern "C"` preserves the symbol…
Ha, then you use/compiled a different version. Since a `extern "C"` preserves the symbol name (that is the trick I use to link in a lot of external C++ code: just put extern "C" in front of the symbol). or it could be that I am completely missing something here. [for example: is the symbol `DLL_EXPORTS` defined at compile time?]

Hum, "just put extern "C" in front of the symbol" (no capito ;-( )

PS : Here the prototype-code of the Linux Pascal Wrapper i use :

PS2 : We gonna get it, im sure...

Fred van Stappen
to Ludo Brands: That routine is defined in SoundTouchDLL.cpp which is the windows dll wrapper. Do you…
That routine is defined in SoundTouchDLL.cpp which is the windows dll wrapper. Do you have the linux equivalent?

Oops, im full of doubt now...
Do you think the SoundTouchDLL.h wrapper is for Windows only ( and, yes, the old wrapper uses stdcall (who is windows only)).

And for linux how does the programmers to link to the library without wrapper ?

Im loosed...

Ewald
to Fred van Stappen: Hum, "just put extern "C" in front of the symbol" (no capito ;-( ) PS : Here the…
Fred van Stappen wrote 6 lines
>Ha, then you use/compiled a different version. Since a `extern "C"` preserves > the symbol name (that is the trick I use to link in a lot of external C++ code: >just put extern "C" in front of the symbol). or it could be that I am completely >missing something here. [for example: is the symbol `DLL_EXPORTS` defined at compile time?] Hum, "just put extern "C" in front of the symbol" (no capito ;-( )

What I'm trying to say is that if there is `extern "C"` in front of a symbol, C++ won't mangle the name. In the cpp file you attached in one of your previous mails, [assuming a C++ compiler] this is the case as per the expansion of the macro `SOUNDTOUCHDLL_API`; on one condition: that `DLL_EXPORTS` is defined.

[hint: read ahead to the second part first as it might just solve your problem]

Since you see mangled names, there must be an error or version mismatch somewhere in your build of the library. So I thought that perhaps you are using a compiled version of the library that still uses stdcall instead of cdecl.

To get closer to the bug, try the following:
- Compile with debug symbols everwhere (there is no such thing as overkill ;-) )
- Run your program in gdb and get a backtrace (`bt` on the command line of gdb), if the crash occurs at the end of the function in the library, or just after the call, then it might be a calling convention issue. If I am informed correctly (see http://stackoverflow.com/questions/3404372/stdcall-and-cdecl) then the difference between stdcall and cdecl lies in who cleans up the stack. A mismatch results in the stack being cleaned up twice or rather inconvenient to normal program flow. If this is the case, try changing calling conventions.

PS2 : We gonna get it, im sure...

[The Second Part -->] Well, it seems I have found something interresting here (as already suggested by Marco); you don't define THandle in your library wrapper. THandle is defined as a longint (http://www.freepascal.org/docs-html/rtl/system/thandle.html), but you need a pointer.

Try putting `Type THandle = pointer;` somewhere before the first usage of this type in your library wrapper.

Ewald
Fred van Stappen
to Ewald

Yep, yep, yep, i get it...

I will (try) to explain the thing...
The error comes mainly because i was focused on SoundTouchDLL.h. (Thanks to Ludo).

That wrapper is for windows only.

Before to call a DSP-buffer-procedure, you must do :
FHandle := soundtouch_createInstance();

But the result of nm libSoundTouch.so gives 3 different soundtouch_createInstance() :

_ZN10soundtouch14TransposerBase11newInstanceEv
_ZN10soundtouch9FIRFilter11newInstanceEv
_ZN10soundtouch9TDStretch11newInstanceEv

The same (for example) for setChannels :

_ZN10soundtouch14TransposerBase11setChannelsEi
_ZN10soundtouch9TDStretch11setChannelsEi
_ZN10soundtouch14RateTransposer11setChannelsEi

And after creating new instance, you must use the procedure of the kind of instance : _ZN10soundtouch9TDStretch11newInstanceEv
with _ZN10soundtouch9TDStretch11setChannelsEi

And all the procedures defined by SoundTouchDLL.h are not working because the "general" function soundtouch_createInstance() is not part of the library ( or i do not find it ) , all the "general" soundtouch procedure cannot work :

ZN10soundtouch10SoundTouch11setChannelsEj (and all the "general" others) ______________

Now, conclusion of that hard battle :

1) With fpc, there is ALWAYS a solution.
2) Without the help of Ludo, Ewald and Marco i never would find that solution.
3) If you want create pascal wrappers I highly recommend to use "nm the_problematic_lib.so" and analyse carefully the result.
4) Dynlibs.pas is working perfectly and (for me) one of the most important part of fpc (because it opens fpc to other worlds).

Biggest thank for helping.
Have perfect days.

PS : I will post the definitive wrapper when everything is working.