How to dynamic load a library?

New to FreeBASIC? Post your questions here.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

How to dynamic load a library?

Post by systemctl »

In a cross platform way, though. The Pascal guys have the dynlibs unit.

https://www.freepascal.org/docs-html/cu ... index.html

I think we currently have none.
Imortis
Moderator
Posts: 1924
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: How to dynamic load a library?

Post by Imortis »

Moved to Beginners Forum.
UEZ
Posts: 988
Joined: May 05, 2017 19:59
Location: Germany

Re: How to dynamic load a library?

Post by UEZ »

systemctl wrote:In a cross platform way, though. The Pascal guys have the dynlibs unit.

https://www.freepascal.org/docs-html/cu ... index.html

I think we currently have none.
Check out the help file for

DyLibSymbol
DyLibLoad
DyLibFree

Or here: https://www.freebasic.net/wiki/wikka.ph ... dLibraries

I'm not sure if this is a Windows only feature.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How to dynamic load a library?

Post by dodicat »

dylibload, dylibsymbol, dylibfree are both Linux and Windows.
Example for Windows:

Code: Select all


width 120,90 'set the console wide enough

dim as any ptr L=dylibload("msvcrt.dll")

print "Addreses"
print L,"msvcrt.dll"

dim shared as function(as ulong, as any ptr,as long) as any ptr UlongToString
UlongToString=dylibsymbol(L,"_ultoa")

dim shared as function(as zstring ptr, as any ptr ptr,as long) as long StringToUlong
StringToUlong=dylibsymbol(L,"strtoul")

print UlongToString,"_ultoa"
print StringToUlong,"strtoul"
print
print "Usage:"


function ULongToBase(N as ulong,_base as byte) as string
    dim as zstring * 50 buffer
    UlongToString(n,@buffer,_base)
    return ucase(buffer)
end function

function ULongFromBase(N as string,_base as byte) as ulong
    return StringToUlong(n,0,_base)
end function

 Union switch
    As single float
    As Ulong value
End Union

function floattobase(n as single,b as byte) as string
    dim as switch z
    z.float=n
    return UlongToBase(z.value,b)
end function

function floatfrombase(s as string,b as byte) as single
    dim as switch z
    z.value=UlongFromBase(s,b)
    return z.float
end function

dim as single z
randomize
for n as long=2 to 36
    z=rnd*1000-rnd*1000
    var s=floattobase(z,n)
    var f=floatfrombase(s,n)
    print "number ";tab(10);z;tab(20);"  base ";n;" = ";s;tab(70);" return ";f;tab(90);"   compare ";cbool(f=z)
next
sleep
DyLibFree(L)


 
_ultoa is not available in Linux, so the above code is windows only.
But the same idea is OK in Linux with other dynamic libraries (.so files)

You can also use loadlibraryex from windows.bi, dylibsymbol works OK with this method.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: How to dynamic load a library?

Post by caseih »

I know your code is an example, but be warned dynamically loading msvcrt.dll is not recommended. That's because a version of the standard C runtime dll is already in memory--all FB programs load it and you can access any symbol in it already. Dynamically loading a different version of msvcrt.dll into a process can cause undefined behavior (crash or data loss), especially when dealing with files. That's because msvcrt.dll initializes certain global memory locations on loading. Different versions will conflict.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to dynamic load a library?

Post by jj2007 »

caseih wrote:I know your code is an example, but be warned dynamically loading msvcrt.dll is not recommended. That's because a version of the standard C runtime dll is already in memory--all FB programs load it and you can access any symbol in it already. Dynamically loading a different version of msvcrt.dll into a process can cause undefined behavior (crash or data loss), especially when dealing with files. That's because msvcrt.dll initializes certain global memory locations on loading. Different versions will conflict.
So does FB load a version that is different from "msvcrt.dll"? Which version does it load then?
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: How to dynamic load a library?

Post by dodicat »

It is true that msvcrt.dll is omnipresent.
Note that crt.bi loads the .dll also, and as far as I can tell it doesn't have to.
All you need are declarations and BINGO you have it.


dylibload loads the library in a completely separate location.

Code: Select all


dim as any ptr L=dylibload("msvcrt.dll")


print "Addresses dylib"
print L,"msvcrt.dll"

dim shared as function(as ulong, as any ptr,as long) as any ptr UlongToString
UlongToString=dylibsymbol(L,"_ultoa")

dim shared as function(as zstring ptr, as any ptr ptr,as long) as long StringToUlong
StringToUlong=dylibsymbol(L,"strtoul")

print UlongToString,"_ultoa"
print StringToUlong,"strtoul"
print

'================ ONLY NEED DECLARATIONS MSVCRT IS LOADED ANYWAY 
declare function _ultoa cdecl alias "_ultoa"(as ulong, as any ptr,as long) as any ptr
declare function strtoul cdecl alias "strtoul"(as zstring ptr, as any ptr ptr,as long) as long
print "Addresses of pre loaded functions:"
print @_ultoa,"_ultoa  crt"
print @strtoul,"strtoul  crt"

sleep
DyLibFree(L)
  
But I agree with casieh, my code is only an example, and there is absolutely no reason to load msvcrt.dll with dylib.
As far as it being not recommended I also tend to agree, it is the first time I have tried it (I tend not to use dylibload).
Similar I suppose with kernel32.dll and the other system dll's, no need to load them.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: How to dynamic load a library?

Post by caseih »

jj2007 wrote:So does FB load a version that is different from "msvcrt.dll"? Which version does it load then?
Possibly. msvcrt.dll is very old--dates back to Visual Studio 6 days. It's still always available, though, for backwards compatibility. The version of msvcrt that FB uses depends on the version of the Mingw toolchain it uses. Up until a few years ago, Mingw always used the old msvcrt.dll. Recent versions of Mingw may have changed that, at least that's what I remember reading. But I actually can't find definitive information on which version Mingw uses now.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to dynamic load a library?

Post by systemctl »

caseih wrote:
jj2007 wrote:So does FB load a version that is different from "msvcrt.dll"? Which version does it load then?
Possibly. msvcrt.dll is very old--dates back to Visual Studio 6 days. It's still always available, though, for backwards compatibility. The version of msvcrt that FB uses depends on the version of the Mingw toolchain it uses. Up until a few years ago, Mingw always used the old msvcrt.dll. Recent versions of Mingw may have changed that, at least that's what I remember reading. But I actually can't find definitive information on which version Mingw uses now.
If it's anything related with the default WINVER and _WIN32_WINNT on MinGW it's set to Windows Server 2003.

I got a list of them from there: https://docs.microsoft.com/en-us/cpp/po ... ew=vs-2019
Last edited by systemctl on Apr 30, 2020 15:32, edited 1 time in total.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to dynamic load a library?

Post by systemctl »

UEZ wrote:
systemctl wrote:In a cross platform way, though. The Pascal guys have the dynlibs unit.

https://www.freepascal.org/docs-html/cu ... index.html

I think we currently have none.
Check out the help file for

DyLibSymbol
DyLibLoad
DyLibFree

Or here: https://www.freebasic.net/wiki/wikka.ph ... dLibraries

I'm not sure if this is a Windows only feature.
Thanks. And sorry because I didn't check the Wiki before ask.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to dynamic load a library?

Post by systemctl »

dodicat wrote:dylibload, dylibsymbol, dylibfree are both Linux and Windows.
Example for Windows:

Code: Select all


width 120,90 'set the console wide enough

dim as any ptr L=dylibload("msvcrt.dll")

print "Addreses"
print L,"msvcrt.dll"

dim shared as function(as ulong, as any ptr,as long) as any ptr UlongToString
UlongToString=dylibsymbol(L,"_ultoa")

dim shared as function(as zstring ptr, as any ptr ptr,as long) as long StringToUlong
StringToUlong=dylibsymbol(L,"strtoul")

print UlongToString,"_ultoa"
print StringToUlong,"strtoul"
print
print "Usage:"


function ULongToBase(N as ulong,_base as byte) as string
    dim as zstring * 50 buffer
    UlongToString(n,@buffer,_base)
    return ucase(buffer)
end function

function ULongFromBase(N as string,_base as byte) as ulong
    return StringToUlong(n,0,_base)
end function

 Union switch
    As single float
    As Ulong value
End Union

function floattobase(n as single,b as byte) as string
    dim as switch z
    z.float=n
    return UlongToBase(z.value,b)
end function

function floatfrombase(s as string,b as byte) as single
    dim as switch z
    z.value=UlongFromBase(s,b)
    return z.float
end function

dim as single z
randomize
for n as long=2 to 36
    z=rnd*1000-rnd*1000
    var s=floattobase(z,n)
    var f=floatfrombase(s,n)
    print "number ";tab(10);z;tab(20);"  base ";n;" = ";s;tab(70);" return ";f;tab(90);"   compare ";cbool(f=z)
next
sleep
DyLibFree(L)


 
_ultoa is not available in Linux, so the above code is windows only.
But the same idea is OK in Linux with other dynamic libraries (.so files)

You can also use loadlibraryex from windows.bi, dylibsymbol works OK with this method.
Thanks for your example. Very helpful.
systemctl
Posts: 182
Joined: Mar 27, 2020 5:15

Re: How to dynamic load a library?

Post by systemctl »

caseih wrote:
jj2007 wrote:So does FB load a version that is different from "msvcrt.dll"? Which version does it load then?
Possibly. msvcrt.dll is very old--dates back to Visual Studio 6 days. It's still always available, though, for backwards compatibility. The version of msvcrt that FB uses depends on the version of the Mingw toolchain it uses. Up until a few years ago, Mingw always used the old msvcrt.dll. Recent versions of Mingw may have changed that, at least that's what I remember reading. But I actually can't find definitive information on which version Mingw uses now.
I'm using MinGW64 8.1 shipped together with CodeBlocks 64 bit version and it's still default to Windows Server 2003 as I mentioned above.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: How to dynamic load a library?

Post by caseih »

I don't think the winver stuff has anything to do with it. The msvcrt dlls come in different flavors, with the version in the file name. msvcrt70.dll etc. These correspond to the Visual C compiler versions, not the windows versions. Unfortunately only certain versions ever shipped with the OS. Every new version of Visual Studio had its own version of the runtime that it used. In Windows 10, and also 8, MS has released what they call a universal C runtime dll. This removes the link between the C compiler version (Visual Studio version) and the C runtime version, putting the runtime under control of the OS. Over the years there were lots of problems with software requiring a particular version that needed to be downloaded separately and installed (or shipped with the program). The universal runtime solved that problem, and eventually mingw will move to linking against it.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: How to dynamic load a library?

Post by jj2007 »

dodicat wrote:dylibload loads the library in a completely separate location.

Code: Select all

print "Addresses of pre loaded functions:"
asm
  int 3
  lea eax, [_ultoa]
  mov edx, UlongToString
end asm
It turns out that both end up at exactly the same location. Which is not surprising - there is only one DLL with that name in C:\Windows\System32
robert
Posts: 169
Joined: Aug 06, 2019 18:45

Re: How to dynamic load a library?

Post by robert »

caseih wrote:I don't think the winver stuff has anything to do with it. The msvcrt dlls come in different flavors, with the version in the file name. msvcrt70.dll etc. These correspond to the Visual C compiler versions, not the windows versions. Unfortunately only certain versions ever shipped with the OS. Every new version of Visual Studio had its own version of the runtime that it used. In Windows 10, and also 8, MS has released what they call a universal C runtime dll. This removes the link between the C compiler version (Visual Studio version) and the C runtime version, putting the runtime under control of the OS. Over the years there were lots of problems with software requiring a particular version that needed to be downloaded separately and installed (or shipped with the program). The universal runtime solved that problem, and eventually mingw will move to linking against it.
Hi caseih:

Martin Storsjö at MinGW-64 has been working on this for more than two years. An overview given in one of his posts in March 2019 is interesting. Here's the link

https://sourceforge.net/p/mingw-w64/mai ... /36621319/

You may also like to look at this Stackoverflow thread. "How do I build against the UCRT with mingw-w64?"

https://stackoverflow.com/questions/575 ... -mingw-w64
Post Reply