The other day I was writing some code for a native plugin in Unity, and as I got ready to try my code in the editor for the first time, I was hit with an EntryPointNotFoundException.
This particular exception tells me that there wasn't a problem loading the DLL (that would be a DllNotFoundException, which happens whether it isn't found or whether it fails to load because for example a dependency is missing or it has the wrong bitness).
Here are a few things I would normally check.
__declspec(dllexport)
will set you on the right path. Learn about dllexport.extern "C"
to avoid name mangling.My quick scan didn't find anything, so I decided to whip up the ol' debugger.
First, you can get WinDBG from the Microsoft Store. Easy enough, and nothing fancy required.
Next, start it up and attach it to the Unity editor process, which will be named Unity.exe
; no need to worry about all the various helper processes.
Next, run .sympath
to check your symbol path. You should have the SRV*https://msdl.microsoft.com/download/symbols
Microsoft public symbol server already included.
You can add the Unity symbols with .sympath+ SRV*c:\symbols*http://symbolserver.unity3d.com/
.
Depending on what kind of debugging you're planning on doing, your graphics driver symbols are also handy to have, for example .sympath+ SRV*c:\symbols*https://driver-symbols.nvidia.com/
Now, at this point, I want to troubleshoot the function lookup, which is what's likely failing. I can do this with bp KERNEL32!GetProcAddressStub
(one of the LoadLibrary functions would be used to troubleshoot a DllNotFoundException
). Then run with g
, and manually trigger the codepath that does the failing P/Invoke.
The path will include a bunch of Mono functions for which you should have symbols (how to get Mono sources is an exercise for another day).
Going up the stack, I can see the function name and also a reference to MonoDl
. A quick search in the GitHub mono repo shows that this is the "dynamic linker" support in Mono, and that led me to the root of my problem.
The main_module
field in the structure being used was set to 1, which means it's going to try and lookup from the Unity module - this was because I got my #if
statements wrong in my C#, and was linking to __Internal
on Windows instead of the correct DLL name. I was able to corroborate this by taking the module handle (0x7ff6bf6e0000
in my case) which matched the Unity module I got from lm
.
A quick lookup in the define directives reference in Unity got me all sorted out, and it all worked out in the end.
Happy Unity debugging!