rlabrecque / Steamworks.NET

Steamworks wrapper for Unity / C#
http://steamworks.github.io
MIT License
2.81k stars 368 forks source link

DllNotFoundException on OS X #23

Closed merfolk closed 9 years ago

merfolk commented 10 years ago

I am having trouble getting Steamworks.NET working on an OS X port of a Monogame-based game. The Steamworks integration is already working on Windows.

I have downloaded the complete Steamworks.NET-Standalone_5.0.0 release and added a reference to the OSX-Linux-x86/Steamworks.NET.dll in my project.

I have then manually copied steam_appid.txt (changing the appid to our own), CSteamworks.bundle, and Steamworks.NET.dll.config files inside our Game.app/Contents/MonoBundle/ folder, right next to the Game.exe.

However, when I launch the game I get this exception from Steamworks.SteamAPI.Init():

System.DllNotFoundException: CSteamworks.bundle/Contents/MacOS/CSteamworks at at (wrapper managed-to-native) Steamworks.NativeMethods.SteamAPI_InitSafe () <IL 0x00011, 0x0008f> at at Steamworks.SteamAPI.Init () <IL 0x00005, 0x0002b>

What have I missed?

Any help would be highly appreciated, as this is one of the very last problems that our team has before releasing our first game on Steam. Thanks!

merfolk commented 9 years ago

I was able to get rid of the System.DllNotFoundException by using an absolute path in the steamworks.NET.dll.config file, e.g.

<dllmap os="osx" dll="CSteamworks" target="/Users/*my_username*/*path_to_repo*/bin/Debug/*game*.app/Contents/MonoBundle/CSteamworks.bundle/Contents/MacOS/CSteamworks"/>

Of course using an absolute path like this won't work for anyone else except me. I tried dropping dropping folders one by one from the start of that absolute path, but absolutely nothing worked except the full absolute path.

And the problems don't end there. I have copied steam_appid.txt, with the correct appID, to every level after the Debug folder, but I am still getting this error:

[S_API FAIL] SteamAPI_Init() failed; no appID found. Either launch the game from Steam, or put the file steam_appid.txt containing the correct appID in your game folder. KQ: Error reading KQ:Interrupted system call

rlabrecque commented 9 years ago

Hey Sorry, I had missed this the first time around! I'll have a look into how I did it again, It was kind of finicky in general. Did you try it out with Steamworks.NET-StandaloneTest at all?

Something that I haven't tested with at all is with a non Unity .app, I only ever tested it out running a .exe directly through mono.

merfolk commented 9 years ago

Thank you for replying. :)

I believe I came across the StandaloneTest, but I will take a look at it again.

The steam_appid.txt seems to work only when the game has been downloaded and launched from Steam, and not when running the game from e.g. /bin/Release. Maybe the original Steamworks API only looks for the txt file from the Steam folders, I didn't try just putting it there and launching the game from it's build folder.

However the absolute path required for CSteamworks to be found is still an issue.

merfolk commented 9 years ago

I tested the Steamworks.NET-StandaloneTest just now. When running it through Xamarin Studio, it never even enters the main, but does not fail either. When running it from bash using mono Steamworks.NET_StandaloneTest.exe it throws the following error, even though CSteamworks.dll is sitting right next to the exe:

Unhandled Exception: System.TypeInitializationException: An exception was thrown by the type initializer for SteamworksNET_StandaloneTest.Program ---> System.DllNotFoundException: CSteamworks at (wrapper managed-to-native) Steamworks.NativeMethods:SteamAPI_RegisterCallback (intptr,int) at Steamworks.Callback1[Steamworks.PersonaStateChange_t].Register (Steamworks.DispatchDelegate func) [0x00000] in <filename unknown>:0 at Steamworks.Callback1[Steamworks.PersonaStateChange_t]..ctor (Steamworks.DispatchDelegate func, Boolean bGameServer, Boolean bKeepAlive) [0x00000] in :0 at Steamworks.Callback`1[Steamworks.PersonaStateChange_t].Create (Steamworks.DispatchDelegate func) [0x00000] in :0 at SteamworksNET_StandaloneTest.Program..cctor () [0x00000] in :0

merfolk commented 9 years ago

I used MONO_LOG_LEVEL=debug mono Steamworks.NET_StandaloneTest.exe to get the paths where mono is trying to find the CSteamworks library.

Mono: DllImport attempting to load: 'CSteamworks'. Mono: DllImport error loading library '.../Steamworks.NET-StandaloneTest/bin/Debug/libCSteamworks': 'dlopen(.../Steamworks.NET-StandaloneTest/bin/Debug/libCSteamworks, 9): image not found'.

And the same thing for libCsteamworks.dylib, .so, and .bundle.

Where does the lib-prefix come from?

Unfortunately I have no idea how to get the same logging information from the actual game, since it's an app bundle and trying to run the .exe alone will just whine about Info.plist file missing.

Eversor commented 9 years ago

Hey merfolk, where you able to solve the issue? I'm having some problem as well in Xamarin Studio.

merfolk commented 9 years ago

Unfortunately I have not had time to wrestle with this issue.

My best guess is that the Steamworks.NET dll is actually trying to find a file named "libCSteamworks" instead of "CSteamworks". That's what I would try next.

strich commented 9 years ago

FYI the lib prefix comes from Mono itself - It will attempt to find libs with that prefix along with a bunch of others (With and without extension, etc). More info here: http://www.mono-project.com/docs/advanced/pinvoke/dllmap/

Given the appid file error though I'd say there is some issue with Steamworks correctly determining the relative directory of your game.

Eversor commented 9 years ago

I finally had it to work on my Xamarin configuration. The problem was the signing of the mac bundle. Removing signing did the trick. (working on debug and release, both without signing)

rlabrecque commented 9 years ago

Awesome! I'm glad to hear that you figured that out!