-
-
Notifications
You must be signed in to change notification settings - Fork 420
Description
I'm using Steamworks.NET Standalone version 2025.163.0 on Linux with Godot. The project builds, but at runtime, I get errors:
ERROR: [Steamworks.NET] Could not load [lib]steam_api.dll/so/dylib. It's likely not in the correct location. Refer to the README for more details.
ERROR: System.DllNotFoundException: Unable to load shared library 'steam_api' or one of its dependencies. In order to help diagnose loading problems, consider using a tool like strace. If you're using glibc, consider setting the LD_DEBUG environment variable:
ERROR: /usr/lib/dotnet/shared/Microsoft.NETCore.App/9.0.11/steam_api.so: cannot open shared object file: No such file or directory
ERROR: /usr/lib/dotnet/shared/Microsoft.NETCore.App/9.0.11/libsteam_api.so: cannot open shared object file: No such file or directory
ERROR: /usr/lib/dotnet/shared/Microsoft.NETCore.App/9.0.11/steam_api: cannot open shared object file: No such file or directory
ERROR: /usr/lib/dotnet/shared/Microsoft.NETCore.App/9.0.11/libsteam_api: cannot open shared object file: No such file or directory
I created a Post-Build copy script for libsteam_api.so and steam_appid.txt, and I verified that they are being copied into the output directory.
The problem:
DLLImport is searching the wrong location for libsteam_api.so. I think it's on these lines: It's searching in /usr/lib/dotnet/ instead of the project root. I verified that this is the problem by setting the LD_LIBRARY_PATH environment variable, which DLLImport uses to determine where to search.
Temp workaround:
When LD_LIBRARY_PATH is set to the project root and libsteam_api.so is in the project root, the game runs fine.
Real solutions:
-
Add
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]above the DLLImport lines in Steamworks.NET. -
Alternatively, SteamManager.cs can be modified (tested and working on Godot Linux, untested on other platforms):
private void HookSteamDllResolver()
{
NativeLibrary.SetDllImportResolver(typeof(SteamAPI).Assembly, (libraryName, assembly, searchPath) =>
{
// Ignore assemblies that are not the Steam API library (might be unnecessary)
if (libraryName != "steam_api") return IntPtr.Zero;
// Determine the correct filename based on the platform
string nativeFile = "steam_api64.dll"; // Default Windows
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
nativeFile = "libsteam_api.so";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
nativeFile = "libsteam_api.dylib";
}
// Check next to the executing assembly
string localPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, nativeFile);
if (File.Exists(localPath))
{
GD.Print("Found it in executing assembly directory");
return NativeLibrary.Load(localPath);
}
// Failed to find it
return IntPtr.Zero;
});
}
public override void _EnterTree()
{
if (Instance == null)
Instance = this;
else
{
QueueFree();
return;
}
HookSteamDllResolver();
...
}