Jump to content

Recommended Posts

Hello,

 

Testing the AVIF image code (https://github.com/Xelitan/AVIF-and-HEIC-for-Delphi-Lazarus/) and have a question about dlls.

 

(https://en.delphipraxis.net/topic/9060-anyone-know-of-an-avif-image-decoder-for-delphi/?tab=comments#comment-106499)

 

The code uses static dll linking:

const LIBHEIF = 'libheif.dll';  
function heif_context_alloc: PHeifContext; cdecl; external LIBHEIF;

I want to put the dll in a sub-directory of the exe, I use:

const LIBHEIF = '.DLL\AVIF\libheif.dll';

That works for the “libheif.dll” but, not the other three dlls that are used by “libheif.dll”.

 

When running that application, I get:

“The code execution cannot proceed because dav1d.dll was not found. Reinstalling the program may fix this problem.”

for the other three dlls.

 

Question one, is there a method to have the other three dlls use the path of the calling dll?

 

Question two, if I go to the trouble of modifying the code for dynamic linking for the “libheif.dll”, would it solve issue? I assume it would not.

 

Ideas?

 

Thanks,

 

Mark

Edited by Mark-

Share this post


Link to post

What you are asking for can't be done if you use static linking. You would have to modify the system PATH in order to find the secondary DLLs that libheif.dll uses.

 

You need to load libheif.dll dynamically at runtime instead. You can either rewrite your code to load libheif's function(s) explicitly via manual calls to LoadLibrary()+GetProcAddress(), or you can simply mark the functions as delayed to let the RTL handle the loading for you. But either way, this will allow you to call SetDllDirectory() or AddDllDirectory() at runtime before you call any of libheif's functions for the first time. 

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post
8 minutes ago, Remy Lebeau said:

What you are asking for can't be done if you use static linking. You would have to modify the system PATH in order to find the secondary DLLs.

 

Thanks. 

That is what I thought.

When exploring options I looked at "delayed". I will give it a go.

 

I also wondered if I declared one function from each of the three dlls, (required by the "main" dll) and, used static linking for the the three dlls, if that would work.

 

Share this post


Link to post
39 minutes ago, Mark- said:

I also wondered if I declared one function from each of the three dlls, (required by the "main" dll) and, used static linking for the the three dlls, if that would work.

No, it will not work.

 

Although it will load the DLLs at process startup, you have no control over the order in which static-linked DLLs are loaded.  More importantly, you CANNOT specify the paths where to search for static-linked DLLs, The resulting IMPORTS table simply does not contain paths, only filenames.  Statically-linked DLLs are always searched for in system-defined paths only, see: Dynamic-link library search order. So, if your app needs to control the paths where DLLs are loaded from, then you MUST use dynamic/delayed loading.

Share this post


Link to post
4 minutes ago, Remy Lebeau said:

No, it will not work.

Thanks

I did not think it would work. 

 

Also testing shows, if all the dlls are in the exe path, all works as expected.

Setting all functions to delayed and calling SetDllDirectory before any function is called, it fails, on the first call to the main dll, with:

 

image.png.a811444125bfbd62759d9d79a471ee80.png

 

image.thumb.png.847ff91bb6dbb3f9c0091937c523c655.png

 

I tired several path options, no joy.

 

Thanks for your help.

 

Share this post


Link to post
9 hours ago, Mark- said:

Also testing shows, if all the dlls are in the exe path, all works as expected.

As it should. That is one of the pre-defined places where the DLL loader looks for dependant DLLs.

9 hours ago, Mark- said:

Setting all functions to delayed and calling SetDllDirectory before any function is called, it fails, on the first call to the main dll

That means the DLL could not be loaded. Either you used the wrong path, or a dependency could not be found, etc.

9 hours ago, Mark- said:

I tried several path options, no joy.

Did you try using a Delay Load failure hook to find out exactly what is failing? See the example in Delphi's documentation

  • Like 1

Share this post


Link to post
16 hours ago, Remy Lebeau said:

What you are asking for can't be done if you use static linking. You would have to modify the system PATH in order to find the secondary DLLs that libheif.dll uses.

 

 

 

There is a relatively simple way to do it.

 

SetDllDirectoryA() also works for child processes spawned by the program.  OP (Mark) could write a trivial loader process that first calls SetDLLDirectoryA() and subsequently executes the "real" program.

Share this post


Link to post

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×