- Home /
How do I use .NET 4.5 managed DLL called by a native DLL (Not easy, I swear I read doc)
I work on a game and I have to use some .NET 4.5 code but this is a priori impossible because the mono version used by Unity is too old. I found this solution: unmanaged exports to make a native plugin from C# code. And this works well.
Unfortunately, my plugin uses other projects compiled as portable libraries. I put these DLLs in the same folder as the native dll. But since they are managed, Unity tries to load them and fails at compilation because they are .NET 4.5 (and worse: Xamarin Portable):
Unhandled Exception: System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
I tried to tell Unity not to bother with these DLLs by opting them out but I guess they are not put into the build and as soon as they are loaded in Unity, the editor crashes.
I then get this in the Unity logs:
========== OUTPUTING STACK TRACE ==================
000007FEFD37940D (KERNELBASE) RaiseException
000007FEEAF9AA64 (MSVCR120_CLR0400) _ValidateWrite
00000000772F0C51 (ntdll) RtlRestoreContext
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 000007FEE774F25F)
000007FEE774F25F (clr)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 000007FEE77337A1)
000007FEE77337A1 (clr)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 000007FEE7733FB6)
000007FEE7733FB6 (clr)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 000007FEE772225A)
000007FEE772225A (clr)
000007FEE778B42E (clr) GetMetaDataInternalInterface
000000001E9A2435 (Mono JIT Code) (wrapper managed-to-native) Startup:Prepare ()
000000001E9A2319 (Mono JIT Code) [E:\USER\GUI_Iriel\Assets\Scripts\Startup.cs:60] Startup:Start ()
000000000D136502 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
000007FEEDC83DF7 (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\mini\mini.c:4914] mono_jit_runtime_invoke
000007FEEDBD82A1 (mono) [c:\buildslave\mono-runtime-and-classlibs\build\mono\metadata\object.c:2623] mono_runtime_invoke
000000014039F94F (Unity) scripting_method_invoke
0000000140548BD3 (Unity) ScriptingInvocation::Invoke
000000014037D06F (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
000000014037D6FC (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
000000014037E297 (Unity) MonoBehaviour::Start
0000000140346BF5 (Unity) DelayedCallManager::Update
000000014047387B (Unity) PlayerLoop
0000000140D00947 (Unity) Application::UpdateScene
0000000140D0669D (Unity) Application::EnterPlayMode
0000000140D06F0A (Unity) Application::SetIsPlaying
0000000140D0D02C (Unity) Application::TickTimer
0000000140DC2845 (Unity) SetAppUpdatesPerSecondOSImpl
0000000140DC4EA4 (Unity) WinMain
0000000141387278 (Unity) strerror_s
00000000770959ED (kernel32) BaseThreadInitThunk
00000000772CC541 (ntdll) RtlUserThreadStart
========== END OF STACKTRACE ===========
It seems like the DLLs are simply absent, I guess Unity did not pack them in the build, since it is what I specified.
Do you know how I could use this code? My first guess would be to find a way to put managed DLL in a build without unity trying to compile them. But I do not know if such a thing exists.
EDIT:
I built the game and put all the required DLLs in the folder _Data/Mono. The first (native DLL) is loaded but not the others. I get these logs:
========== OUTPUTING STACK TRACE ==================
7579C42D (KERNELBASE) RaiseException
728E8FDB (clr) CopyPDBs
72A5D607 (clr) CreateHistoryReader
72A657BC (clr) CreateHistoryReader
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 715638A6)
715638A6 (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 715638D2)
715638D2 (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 71563066)
71563066 (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 7156325B)
7156325B (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 715612FB)
715612FB (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 7156152B)
7156152B (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 71561668)
71561668 (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 715617B5)
715617B5 (clrjit)
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 71561802)
71561802 (clrjit)
727C88F9 (clr) CreateAssemblyNameObject
727C8991 (clr) CreateAssemblyNameObject
727C89D3 (clr) CreateAssemblyNameObject
727C8405 (clr) CreateAssemblyNameObject
727C878C (clr) CreateAssemblyNameObject
728D97B5 (clr) CopyPDBs
727AB02B (clr) DllCanUnloadNowInternal
ERROR: SymGetSymFromAddr64, GetLastError: 'Tentative d’accès à une adresse non valide.' (Address: 72792A0C)
72792A0C (clr)
ERROR: SymGetSymFromAddr64, GetLastError: 'Le module spécifié est introuvable.' (Address: 0580A075)
ERROR: SymGetModuleInfo64, GetLastError: 'Une routine d’initialisation d’une bibliothèque de liens dynamiques (DLL) a échoué.' (Address: 0580A075)
0580A075 ((<unknown>))
060C92CF (Mono JIT Code) (wrapper managed-to-native) Startup:Prepare ()
060C9255 (Mono JIT Code) [E:\USER\GUI_Iriel\Assets\Scripts\Startup.cs:61] Startup:Start ()
060BAAAF (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
100F054D (mono) mono_set_defaults
1005D812 (mono) mono_runtime_invoke
0098AABE (Demo_Unity) scripting_method_invoke
00A50D61 (Demo_Unity) ScriptingInvocation::Invoke
00A50DEE (Demo_Unity) ScriptingInvocation::Invoke
00979EE8 (Demo_Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
0097A1EB (Demo_Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
0097AA80 (Demo_Unity) MonoBehaviour::DelayedStartCall
00958237 (Demo_Unity) DelayedCallManager::Update
00A09AAD (Demo_Unity) PlayerLoop
00ABD6E5 (Demo_Unity) PlayerMainWndProc
00ABF601 (Demo_Unity) PlayerWinMain
00E448A8 (Demo_Unity) WinMain
00E7BF99 (Demo_Unity) _get_printf_count_output
75C2338A (kernel32) BaseThreadInitThunk
77319F72 (ntdll) RtlInitializeExceptionChain
77319F45 (ntdll) RtlInitializeExceptionChain
========== END OF STACKTRACE ===========
I am now certain that the DLLs are accessible.
The stack being :
- clr
- clrjit
- clr
- Mono JIT Code
- mono
- Demo_Unity
I tried to run the thing inside visual studio using a test project calling the same functions and everything loads well. In Unity I tried not to call the managed/portable DLLs, Unity use the native, do whatever has to be done, does not crash.
Does anyone knows why the call chain: exe -> native -> portable works inside visual studio but not with unity? Does anyone see a way to solve the problem?
Your answer
Follow this Question
Related Questions
ML.NET in unity 1 Answer
Getting SSH.NET to work in Unity 1 Answer
How to connect a large .Net C# CAD API to Unity? 0 Answers
External dll: namespace recognized by mono, not by UT 2 Answers