Linux Debian下.NET Core加载SDL2.dll失败问题求助
问题背景
在Linux Debian系统中创建.NET Core解决方案:
- 执行命令创建解决方案:
dotnet new sln -n MySolution - 创建类库项目并添加到解决方案:
dotnet new classlib -n MyApp -o MyApp;dotnet sln add MyApp/MyApp.csproj
在项目的csproj文件中添加SDL2-CS.NetCore包引用:
<ItemGroup> <PackageReference Include="SDL2-CS.NetCore" Version="2.0.8" /> </ItemGroup>
项目编译正常,但运行时抛出异常:
Unhandled exception. System.DllNotFoundException: Unable to load shared library 'SDL2.dll' or one of its dependencies.
尝试在csproj中添加配置:
<NativeLibrary Include="/usr/lib/x86_64-linux-gnu/libSDL2.so" />
但问题依旧,.NET仍优先寻找SDL2.dll,尝试寻找.so文件时也出现错误:
/usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.10/libSDL2.dll.so: cannot open shared object file: No such file or directory
目前通过在bin目录创建SDL2.dll指向libSDL2.so的软链接可解决,但方式不够优雅,需要规范的解决方案。
规范解决方案
1. 重写原生库加载逻辑(无需修改第三方库源码)
利用.NET的NativeLibrary.SetDllImportResolver方法,在程序启动时将对SDL2.dll的请求重定向到系统的libSDL2.so:
using System.Runtime.InteropServices; // 在程序入口或初始化代码中添加 NativeLibrary.SetDllImportResolver(typeof(SDL).Assembly, (libraryName, assembly, searchPath) => { if (libraryName.Equals("SDL2.dll", StringComparison.OrdinalIgnoreCase)) { return NativeLibrary.Load("libSDL2.so", assembly, DllImportSearchPath.System32); } return IntPtr.Zero; });
这种方式不需要修改SDL2-CS.NetCore的源码,直接在自己的项目中拦截库加载请求,实现跨平台的库名称映射。
2. 通过csproj配置实现平台-specific的库映射
在项目文件中按操作系统配置原生库,并指定逻辑名称让.NET识别为SDL2.dll:
<PropertyGroup> <!-- 指定目标运行时,可选但推荐 --> <RuntimeIdentifiers>debian-x64;win-x64</RuntimeIdentifiers> </PropertyGroup> <ItemGroup Condition="'$(OS)' == 'Linux'"> <NativeLibrary Include="/usr/lib/x86_64-linux-gnu/libSDL2.so"> <!-- 将库复制到输出目录(可选,若系统已全局安装可省略) --> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <!-- 告诉.NET这个so文件对应的逻辑名称是SDL2.dll --> <LogicalName>SDL2.dll</LogicalName> </NativeLibrary> </ItemGroup>
LogicalName属性是关键,它会覆盖.NET加载时寻找的库名称,让系统的libSDL2.so被当作SDL2.dll加载。
3. 确保系统已正确安装SDL2依赖
首先通过Debian包管理器安装SDL2的运行时库:
sudo apt-get update && sudo apt-get install libsdl2-2.0-0
这一步确保系统标准路径下存在libSDL2.so,避免因库缺失导致的加载失败。
内容的提问来源于stack exchange,提问作者MatthieuHAMEL

