Skip to content

fix: Change the order of probing for loading native libraries#3033

Merged
Eideren merged 2 commits intostride3d:masterfrom
Ethereal77:fix/library-loader
Jan 25, 2026
Merged

fix: Change the order of probing for loading native libraries#3033
Eideren merged 2 commits intostride3d:masterfrom
Ethereal77:fix/library-loader

Conversation

@Ethereal77
Copy link
Contributor

This PR modifies the order in which NativeLibraryHelper in Stride.Core tries different strategies for locating the native libraries to load, so it tries first the Stride custom ones, and defers the default .NET strategy as a fallback.

PR Details

Some context. I was running the tests in Stride.Graphics.Tests and found that all tests that made use of fonts, text rendering, etc., were being aborted (not failing) with the following error:

Fatal error.
0xC0000005
   at SharpFont.FT.FT_Render_Glyph(IntPtr, SharpFont.RenderMode)
   at SharpFont.GlyphSlot.RenderGlyph(SharpFont.RenderMode)
   at Stride.Graphics.Font.FontManager.RenderBitmap(Stride.Graphics.Font.CharacterSpecification, SharpFont.Face)
   at Stride.Graphics.Font.FontManager.GenerateCharacterGlyph(Stride.Graphics.Font.CharacterSpecification, Boolean)

After some investigation, I found that NativeLibraryHelper was trying to load freetype (a native dependency) using the default loading mechanism of .NET, even though that class implements strategies to find native libraries better suited to the custom nature of what Stride needs. The problem was that the tests were sometimes loading the wrong versión of some of our native dependencies.

It seems the .NET default strategy (NativeLibrary.TryLoad) was trying to look for freetype.dll in the directory where the executable is, the directory where the P/Invoking module is, the current directory, in C:\Windows\System32, etc., and finally, in the paths in the environment PATH variable.

So, instead of finding our version of freetype in /runtimes/win-x64, it was loading a different (and incompatible) version it found in C:\Users\Mario\AppData\Local\Microsoft\WinGet\Packages\oschwartz10612.Poppler_Microsoft.Winget.Source_8wekyb3d8bbwe\poppler-25.07.0\Library\bin\freetype.DLL.
And not only with freetype. Instead of loading our version of d3d3dcompiler_47.dll, it was loading C:\WINDOWS\SYSTEM32\d3dcompiler_47.DLL (this one is not a problem because they are identical).

So, I've restructured and reordered the logic a bit to first look for libraries using our custom logic, and only if none is found, fallback to the default logic. With this change, tests started running and passing as before this problem arised.

I have also:

  • Modernized the NativeLibraryLoader class.
  • Added new documentation and improved the existing one, and the comments.
  • Added a debug switch and logic to be able to diagnose library loading problems in the future.

Related Issue

There are several I've found: #1692 #1750
Possibly also #1700 (the incorrectly loaded library does not manifest as crashes sometimes, but as corrupt data or wrong font metrics, etc.)

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

* Also, modernize the `NativeLibraryLoader` class.
* Add documentation, improve the existing comments.
* Add debug switch to diagnose library loading problems.
@Kryptos-FR
Copy link
Member

Does it work and/or fix issues with code-only projects on Linux? I remember we had a few issues related to dlls that needed to be copied over.

@Ethereal77
Copy link
Contributor Author

Ethereal77 commented Jan 14, 2026

I can't test it on Linux. If anyone can verify...
In principle, the logic to test for Linux/MacOS-specific paths is still there, just after our custom logic, but before .NET default strategy.

EDIT: Just to clarify. When I refer to "our custom logic", I'm referring to the search that, starting from where the executable/defining assembly is located, looks inside runtimes/{platform}-{architecture}, and some variations of that. I have not modified that logic. I'm not sure if it covers the case of NuGet packages, where runtimes directory is at the package root, not under the assembly directory. But, if it worked before, this should work the same.

@VaclavElias
Copy link
Contributor

Adding this for a reference #2596 where the manually copied files are mentioned.. it might be related with the general/future Stride coding on Linux, not necessarily only code-only.

@Eideren
Copy link
Collaborator

Eideren commented Jan 24, 2026

Looks good, as Ethereal mentioned, these changes only changes the priority for certain paths when loading in a library. #2596 would be unaffected as it would require new paths to be probed or binaries to be moved to appropriate paths.
If there are no objections, I'll merge this one in tomorrow as well.

@Eideren Eideren merged commit 5f52ecc into stride3d:master Jan 25, 2026
9 checks passed
@Eideren Eideren added the area-Core Issue of the engine unrelated to other defined areas label Jan 25, 2026
@Eideren Eideren changed the title Change the order of probing for loading native libraries fix: Change the order of probing for loading native libraries Jan 25, 2026
@Eideren
Copy link
Collaborator

Eideren commented Jan 25, 2026

Thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Core Issue of the engine unrelated to other defined areas

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants