Skip to content

Bring NativeLibraryConfig.WithLibrary to netstandard2.0 (#960) - #1418

Draft
YoMosa2009 wants to merge 1 commit into
SciSharp:masterfrom
YoMosa2009:fix/960-native-library-config
Draft

Bring NativeLibraryConfig.WithLibrary to netstandard2.0 (#960)#1418
YoMosa2009 wants to merge 1 commit into
SciSharp:masterfrom
YoMosa2009:fix/960-native-library-config

Conversation

@YoMosa2009

Copy link
Copy Markdown
Contributor

Draft PR for #960, opening it early so it's easier to review as code instead of me typing paragraphs in the issue.

What this does

NativeLibraryConfig.WithLibrary(path) (and the NativeLibraryConfigContainer version) now works on netstandard2.0, not just net6.0+. If you call it, netstandard2.0 will load that exact file itself via a small P/Invoke shim (LoadLibrary on Windows, dlopen on Linux/mac) that stands in for System.Runtime.InteropServices.NativeLibrary, which doesn't exist on netstandard2.0.

If you don't call WithLibrary, netstandard2.0 behaves exactly like it does on master right now, still a no-op, DryRun still returns false with an UnknownNativeLibrary. So this is purely additive, no behavior change for anyone not opting in (including Unity's own plugin loader, which this doesn't touch at all).

What this deliberately does NOT do

The CUDA/Vulkan/AVX auto-detection backend-selection matrix (DefaultNativeLibrarySelectingPolicy, NativeLibraryWithCuda/Vulkan/Avx, etc.) stays net6.0+ only for now. Porting that for real means replacing System.Runtime.Intrinsics.X86.*/Arm.ArmBase and RuntimeInformation.RuntimeIdentifier, neither of which exist pre-.NET Core 3.0, and it's a much bigger surface to get right and test. Wanted to scope this PR down to what the issue actually asked for. Happy to tackle that separately if it's wanted.

Files touched

  • NativeLibraryConfig.cs: moved WithLibrary/the library path out of the NET6_0_OR_GREATER-only partial class into the shared one.
  • NativeLibraryUtils.cs: netstandard2.0 branch of TryLoadLibrary now checks for an explicit path and loads it if set.
  • PlatformNativeLibrary.cs (new): the LoadLibrary/dlopen shim, only compiled #if !NET6_0_OR_GREATER.
  • UnknownNativeLibrary.cs: doc comment tweak to reflect the new explicit-path case.

Testing

LLama.Unittest only targets net8.0, so it can't exercise the netstandard2.0-only code path directly. I built a throwaway net48 console app (forces netstandard2.0 asset selection through the project reference) and confirmed:

  • WithLibrary(path).DryRun(out lib) actually loads a real Windows DLL and returns NativeLibraryFromPath.
  • Not calling WithLibrary still gives the old no-op behavior (false / UnknownNativeLibrary / LibraryHasLoaded stays false).

I don't have a Linux/macOS box handy to exercise the dlopen path, so that part is reviewed but not runtime-tested by me. Flagging that clearly rather than claiming more than I've verified.

Open question from the issue thread I'd still like input on: should the explicit-path case also preload ggml-base/ggml from the same folder like the net6.0 path does (llama.cpp ships split shared libs), or is it fine to assume netstandard2.0/Unity users are pointing at one self-contained binary for now? Went with the simpler version for this PR, easy to add if wanted.

Closes/relates to #960.

馃 Generated with Claude Code

Expose WithLibrary (and the NativeLibraryConfigContainer overload) on
netstandard2.0, not just NET6_0_OR_GREATER. When an explicit path is
set, netstandard2.0 now loads that file directly via a small
platform-specific P/Invoke shim (LoadLibrary on Windows, dlopen on
Linux/macOS) standing in for System.Runtime.InteropServices.NativeLibrary,
which isn't available on netstandard2.0.

The CUDA/Vulkan/AVX auto-detection backend-selection matrix is left
NET6_0_OR_GREATER-only for now, since it depends on
System.Runtime.Intrinsics and RuntimeInformation.RuntimeIdentifier,
neither of which exist pre-.NET Core 3.0. When WithLibrary isn't
called, netstandard2.0 behavior is unchanged from before this commit.

Manually verified on Windows via a net48 console harness (forces
netstandard2.0 asset selection through a project reference) loading a
real system DLL through NativeLibraryConfig.WithLibrary + DryRun, and
confirmed the no-explicit-path case still behaves exactly as before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017JGeTGbj4FKnmWHPGU82yk
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.

1 participant