Skip to content

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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants