Recent

Author Topic: [SOLVED] Help debugging why LoadLibrary keeps returning zero with sample project  (Read 2557 times)

Gizmo

  • Hero Member
  • *****
  • Posts: 796
I've recently compiled a DLL using the 64-bit MSYS2 MinGW and it compiled successfully. I can browse it using DLL Explorer.

But, I can't load it with LoadLibrary using Lazarus 2.0.12 and FPC 3.2.0 on 64-bit Windows 10.

I have created a small demo project and supplied the DLL in the hope someone might look at it and see if the problem is my code, or the DLL itself.

I have Googled the various reasons that LoadLibrary fails, and all the answers seem to relate to things like permissions or filenames. It keeps returning 0 with me, but I can't see WHY its returning zero, because the name string of the filename shows correctly in the debugger and the permissions are allowed to execute it and the path is valid. I've tried using Unicode string, rawbytestring, and normal string. I've tried using THandle and TLibHandle. Just can't get anything other than 0.

It would be a big help if someone could try it for me and see if they can get a non-zero value? Or has the DLL being made incorrectly? DLL Explorer shows all the valid functions in it.

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.Button1Click(Sender: TObject);
  3. var
  4.   //libFileName : Unicodestring;
  5.   // libFileName : RawByteString;
  6.    libFileName : string;
  7.  
  8.   fLibHandle  : TLibHandle;
  9.   // fLibHandle : THandle;
  10. begin
  11.   fLibHandle := nilhandle;
  12.   //libFileName:=ExtractFilePath(Application.ExeName)+'libewf-v3.dll'; /// gets full path to DLL OK
  13.    libFileName:='libewf-v3.dll';   // if DLL in same folder as exe
  14.   if FileExists(libFileName) then
  15.     begin
  16.     fLibHandle := LoadLibrary(PChar(libFileName)); // Keeps returning zero
  17.     //fLibHandle := dynlibs.LoadLibrary(libFileName);
  18.     //fLibHandle := LoadLibraryA(PAnsiChar(libFileName));  // Windows API method
  19.     if fLibHandle<>nilhandle then
  20.       begin
  21.         Label1.Caption := 'Success';
  22.       end
  23.       else Label1.Caption := 'Failed';
  24.     end;
  25. end;
  26.  

Sample project with the DLL in question here : https://we.tl/t-FeC0iquYgX
« Last Edit: May 11, 2021, 11:55:56 am by Gizmo »
Lazarus 2.0.12 and fpc 3.2.0 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Big Sur
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

Imants

  • Full Member
  • ***
  • Posts: 186
Have you tried to call GetLoadErrorStr if result is 0 or give full path to dll file?

Gizmo

  • Hero Member
  • *****
  • Posts: 796
I've just used Depenancy Walker (old tool but still valid) and it has thrown some errors with the DLL. I think I may have compiled from wrong release link. Re-trying. Will report back. Meanwhile, if anyone can see a problem with the code, recommendations welcome.
Lazarus 2.0.12 and fpc 3.2.0 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Big Sur
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1474
  • Former Delphi 1-7, 10.2 user
As Imants mentioned, you have no error checking!

For example (from a macOS example I wrote):

Code: Pascal  [Select][+][-]
  1.    // load and get the dynamic library handle
  2.    LibHandle := LoadLibrary(PChar('libtest.dylib'));
  3.  
  4.    // check whether loading was successful
  5.    if LibHandle <> 0 then
  6.      begin
  7.        // assign address of the subroutine call to the variable cvtString
  8.        Pointer(cvtString) := GetProcAddress(LibHandle, 'cvtString');
  9.  
  10.        // check whether a valid address has been returned
  11.        if @cvtString <> nil then
  12.          WriteLn(cvtString('hello world'))
  13.        // error message on no valid address
  14.        else
  15.          WriteLn('GetLastOSError1 = ', SysErrorMessage(GetLastOSError));
  16.      end
  17.    else
  18.      // error message on load failure
  19.      WriteLn('GetLastOSError2 = ', SysErrorMessage(GetLastOSError));
Lazarus 2.1 r65061 FPC 3.3.1 r49223 macOS 10.14.6 Xcode 11.3.1
Lazarus 2.1 r65182 FPC 3.3.1 r49223 macOS 11.4 aarch64 Xcode 12.4
Lazarus 2.1 r61574 FPC 3.3.1 r42318 FreeBSD 12.1 amd64 VMware VM
Lazarus 2.1 r61574 FPC 3.0.4 Ubuntu 20.04 Parallels VM
Lazarus 2.0.10 FPC 3.2.0 Win10 Parallels VM

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 667
Two possible reasons:
1) DllMain doesn't return true for DLL_PROCESS_ATTACH.
2) This DLL has some dependencies, that aren't satisfied.
30.04.2021 - DynamicData 4.0 is released and migration to it is completed.
It's more Lazarus-friendly, but still requires full Delphi 2009 support to be ported to Lazarus.
It's time to finally do it, because Delphi 2009 is 12 years old.

MarkMLl

  • Hero Member
  • *****
  • Posts: 2699
As Imants mentioned, you have no error checking!

Be warned that I came across something similar on Linux where somebody had replaced the *content* of a shared library with a linker script: the name and everything were correct and it worked if loading were automatic, but not if the module were opened explicitly by name with the intention of checking and loading the entry points individually.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

jcmontherock

  • Jr. Member
  • **
  • Posts: 69
if I replace the name of your dll with "libmysql.dll" (64 bits) it's work. So it's a problem with your dll.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 667
Your dll depends on following dlls:
msvcrt.dll
zlib1.dll
libwinpthread-1.dll
libcrypto-1_1-x64.dll

Are they accessible to your project? You also need correct version of VC runtime installed.
30.04.2021 - DynamicData 4.0 is released and migration to it is completed.
It's more Lazarus-friendly, but still requires full Delphi 2009 support to be ported to Lazarus.
It's time to finally do it, because Delphi 2009 is 12 years old.

Gizmo

  • Hero Member
  • *****
  • Posts: 796
Thanks jcmontherock for trying that. I hadn't thought of that myself! Good idea. And thanks for helping me narrow down the issue.

Mr M...thanks for those details. I had worked out zlib was required but I didnt realise about the others.

This is enormously frustrating. I have also asked the developer. I understand the reasons for not making a DLL available (security etc) but with a library as big as this, and its dependancies, its very tricky to work out how to compile it from source. I've recently done so for SQLite, and that wasnt too tricky once I got the MinGW environment setup right. But for this I've even resorted to installing 10Gb of Visual Studio 2019 and still couldn't get a valid DLL. Probably because of these dependancies. Very frustrating. It's like being given a car with no engine in it.

I think I'll leave this feature to my next version. I have more pressing things to work on right now. This was just a "nice to have"
Lazarus 2.0.12 and fpc 3.2.0 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Big Sur
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

jcmontherock

  • Jr. Member
  • **
  • Posts: 69
One more point: dll type could be COFF or OMF. Embarcadero gives a program utility for converting thees types. I don't know which type Lazarus is using.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 9336
  • FPC developer.
One more point: dll type could be COFF or OMF. Embarcadero gives a program utility for converting thees types. I don't know which type Lazarus is using.

Static libraries (and import libraries) might be COFF/OMF.  DLLs are all PE(+), or windows won't load them.

Gizmo

  • Hero Member
  • *****
  • Posts: 796
I solved this in the end guys. I added some environment paths to my Advanced Windows Settings relating to bin, and lib folders of MSYS2 and MinGW64. But the real solution was that I needed an additional DLL in the same folder, in addition to Zlib1.dll, and that was C:\msys64\mingw64\bin\libwinpthread-1.dll which was needed. So I copied that to the folder, and all was well.

Thanks for the help.
Lazarus 2.0.12 and fpc 3.2.0 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Big Sur
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

 

TinyPortal © 2005-2018