Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/LibVLCSharp/Shared/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ internal static class ArchitectureNames
internal const string Win64 = "win-x64";
internal const string Win86 = "win-x86";
internal const string MacOS64 = "osx-x64";
internal const string MacOSArm64 = "osx-arm64";
}

[Flags]
Expand Down
58 changes: 44 additions & 14 deletions src/LibVLCSharp/Shared/Core/Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,15 @@ static internal bool LibVLCLoaded
var paths = new List<(string, string)>();
string arch;

#if !NET40 && !NETSTANDARD1_1
if (PlatformHelper.IsMac)
{
arch = Path.Combine(ArchitectureNames.MacOS64, Constants.Lib);
arch = RuntimeInformation.ProcessArchitecture switch
{
Architecture.Arm64 => ArchitectureNames.MacOSArm64,
_ => ArchitectureNames.MacOS64,
};
}

#if !NET40 && !NETSTANDARD1_1
else if (PlatformHelper.IsWindows)
{
arch = RuntimeInformation.ProcessArchitecture switch
Expand All @@ -89,9 +92,8 @@ static internal bool LibVLCLoaded
_ => PlatformHelper.IsX64BitProcess ? ArchitectureNames.Win64 : ArchitectureNames.Win86
};
}
#endif

else
#endif
{
arch = PlatformHelper.IsX64BitProcess ? ArchitectureNames.Win64 : ArchitectureNames.Win86;
}
Expand Down Expand Up @@ -138,11 +140,14 @@ static internal bool LibVLCLoaded

paths.Add((string.Empty, libvlcPath3));

// Add Win64 folders as fallback for WinArm64 to keep compatibility
if (arch == ArchitectureNames.WinArm64)
// Add x64 folders as fallback for ARM64 to keep compatibility
if (arch == ArchitectureNames.WinArm64 || arch == ArchitectureNames.MacOSArm64)
{
var fallbackArchitecture = arch == ArchitectureNames.WinArm64
? ArchitectureNames.Win64 : ArchitectureNames.MacOS64;

var fallbackLibvlcDirPath1 = Path.Combine(Path.GetDirectoryName(libvlcAssemblyLocation)!,
Constants.LibrariesRepositoryFolderName, ArchitectureNames.Win64);
Constants.LibrariesRepositoryFolderName, fallbackArchitecture);

var fallbackLibvlccorePath1 = LibVLCCorePath(fallbackLibvlcDirPath1);
var fallbackLibvlcPath1 = LibVLCPath(fallbackLibvlcDirPath1);
Expand All @@ -151,7 +156,7 @@ static internal bool LibVLCLoaded
if (!string.IsNullOrEmpty(assemblyLocation))
{
var fallbackLibvlcDirPath2 = Path.Combine(Path.GetDirectoryName(assemblyLocation)!,
Constants.LibrariesRepositoryFolderName, ArchitectureNames.Win64);
Constants.LibrariesRepositoryFolderName, fallbackArchitecture);

var fallbackLibvlccorePath2 = LibVLCCorePath(fallbackLibvlcDirPath2);
var fallbackLibvlcPath2 = LibVLCPath(fallbackLibvlcDirPath2);
Expand All @@ -161,9 +166,8 @@ static internal bool LibVLCLoaded

if (PlatformHelper.IsMac)
{
var libvlcPath4 = Path.Combine(Path.Combine(Path.GetDirectoryName(libvlcAssemblyLocation)!,
Constants.Lib), $"{Constants.LibVLC}{LibraryExtension}");
var libvlccorePath4 = LibVLCCorePath(Path.Combine(Path.GetDirectoryName(libvlcAssemblyLocation)!, Constants.Lib));
var libvlcPath4 = Path.Combine(Path.GetDirectoryName(libvlcAssemblyLocation)!, $"{Constants.LibVLC}{LibraryExtension}");
var libvlccorePath4 = LibVLCCorePath(Path.GetDirectoryName(libvlcAssemblyLocation)!);
paths.Add((libvlccorePath4, libvlcPath4));
}

Expand All @@ -188,6 +192,19 @@ static void LoadLibVLC(string? libvlcDirectoryPath = null)
loadResult = LoadNativeLibrary(libvlcPath, out LibvlcHandle);
if (!loadResult)
Log($"Failed to load required native libraries at {libvlcPath}");

#if NET5_0_OR_GREATER
// register custom resolver to load library from provided path
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), (dll, _, _) =>
{
return dll switch
{
Constants.LibraryName => NativeLibrary.Load(libvlcPath),
Constants.CoreLibraryName => NativeLibrary.Load(libvlccorePath),
_ => IntPtr.Zero
};
});
#endif
return;
}

Expand All @@ -197,8 +214,21 @@ static void LoadLibVLC(string? libvlcDirectoryPath = null)
{
LoadNativeLibrary(libvlccore, out LibvlccoreHandle);
var loadResult = LoadNativeLibrary(libvlc, out LibvlcHandle);
if (loadResult)
break;
if (!loadResult) continue;

#if NET5_0_OR_GREATER
// register custom resolver to load library from discovered path
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), (dll, _, _) =>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why make this call right after LoadNativeLibrary succeeded? This looks off.

@AnthonyKwon AnthonyKwon Aug 5, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to filter out working path. I know it feels off, but when I looked for the P/Invoke exception causes (with inserting debug lines), it was coming from DllImport of LibVLCVersion(), and macOS seems to be have no problem at DlOpen() the LibVLC without path change, but calling any method throws error.
maybe I can add && MAC to condition if you're unsure about it :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this is why I'm calling it "workaround". maybe someone else who has better knowledge at low-level can bring better way to do it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. but first as I said. libvlc build is the initial step.

{
return dll switch
{
Constants.LibraryName => NativeLibrary.Load(libvlc),
Constants.CoreLibraryName => NativeLibrary.Load(libvlccore),
_ => IntPtr.Zero
};
});
#endif
break;
}

if (!LibVLCLoaded)
Expand Down