13

I am working on the Unity Plugin project and try to import the c++ native dll from c# file. But I keep getting dllnotfoundexception.

c++ dll code:

extern "C" {
extern __declspec( dllexport ) bool IGP_IsActivated();
}

c# code:

[DllImport("mydll")]
    private static extern bool IGP_IsActivated();

Dll is in place and FIle.Exists work properly. All dependent dlls are present at same hierarchy, but I still end up in dllnotfound exception.

Any help, much appreciated!!

Raj
  • 537
  • 1
  • 5
  • 18

8 Answers8

11

Thanks to this Unity forum post I came up with a nice solution which modifies the PATH-environment variable at runtime:

  • Put all DLLs (both the DLLs which Unity interfaces with and their dependent DLLs) in Project\Assets\Wherever\Works\Best\Plugins.
  • Put the following static constructor into a class which uses the plugin:

    static MyClassWhichUsesPlugin() // static Constructor
    {
        var currentPath = Environment.GetEnvironmentVariable("PATH",
            EnvironmentVariableTarget.Process);
    #if UNITY_EDITOR_32
        var dllPath = Application.dataPath
            + Path.DirectorySeparatorChar + "SomePath"
            + Path.DirectorySeparatorChar + "Plugins"
            + Path.DirectorySeparatorChar + "x86";
    #elif UNITY_EDITOR_64
        var dllPath = Application.dataPath
            + Path.DirectorySeparatorChar + "SomePath"
            + Path.DirectorySeparatorChar + "Plugins"
            + Path.DirectorySeparatorChar + "x86_64";
    #else // Player
        var dllPath = Application.dataPath
            + Path.DirectorySeparatorChar + "Plugins";
    
    #endif
        if (currentPath != null && currentPath.Contains(dllPath) == false)
            Environment.SetEnvironmentVariable("PATH", currentPath + Path.PathSeparator
                + dllPath, EnvironmentVariableTarget.Process);
    }
    
  • Add [InitializeOnLoad] to the class to make sure that the constructor is run at editor launch:

     [InitializeOnLoad]
     public class MyClassWhichUsesPlugin
     {
         ...
         static MyClassWhichUsesPlugin() // static Constructor
         {
             ...
         }
      }
    

With this script there is no need to copy around DLLs. The Unity editor finds them in the Assets/.../Plugins/...-folder and the executable finds them in ..._Data/Plugins-directory (where they get automatically copied when building).

Lars Bilke
  • 4,940
  • 6
  • 45
  • 63
  • 2
    I couldn't get the static to work in Unity 2017.3.1f1. At runtime I got: "UnityException: get_dataPath is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead." I switched it to use Awake() and it worked fine & the editor & in my build. – rusty Mar 22 '18 at 16:30
  • This is actually a very elegant solution which enables usage of external libraries in the edtior mode (for usage with inspector scripts), something that is afaik not easily doable when doing it the "normal" way. – Hafnernuss Apr 09 '19 at 21:47
  • 1
    In my recent testing (Unity 2019.2) it seems that the Plugin-Directory is already added to the `PATH` and the static constructor does not seem to be necessary anymore. Can anyone else confirm this? – Lars Bilke Sep 25 '19 at 07:35
5

Well I got it working. For others who may face this problem, if you have more than one dll, you need to put the secondary dlls at root level of the Unity editor (e.g. C:\Program Files\Unity\Editor) and the actual referenced dll from script into plugins folder. This worked for me.

bleater
  • 5,098
  • 50
  • 48
Raj
  • 537
  • 1
  • 5
  • 18
  • 7
    A better place for the dll files would be in the project folder. Just place the dll files in the same folder as the "Assets" and "Library" folders. – TrolleFar Jul 04 '12 at 00:25
  • @TrolleFar this worked for me, saved me hours of headaches thank you guys for posting the question, answers, and comments! – hsmith Mar 06 '13 at 06:06
  • 2
    I keep get those Exception even I place dll file in project directory and in folder same as exe file after build. Are Visual C++ Redistributable needed? I build dll from Visual C++ 2008 SP1 and installed all Visual C++ 2008 Redistributable available in microsoft website still get exception dll not found in other machine. – Akirayjin Sep 05 '13 at 03:53
  • 3
    I tried all of these solutions for hours... turned out my external DLL was a 32 bit one, and my Unity project was 64-bit. Was getting `DllNotFoundException` so got led down the garden path... another thing to watch out for. – John Lyon Aug 11 '14 at 04:21
  • Tried everything, nothing worked. Please help https://stackoverflow.com/questions/54898629/unable-to-find-type-or-namespace-of-imported-dll – Vipin Verma Feb 28 '19 at 03:02
  • Awesome, this worked (Unity 2018.4). And for anyone else looking at this who's using IL2CPP, you may need to make sure you assembly doesn't get stripped. See https://docs.unity3d.com/Manual/ManagedCodeStripping.html – michael Mar 29 '20 at 21:09
5

Put the DLL(s) Unity interfaces with in Project\Assets\Wherever\Works\Best\Plugins.

Place any dependency DLLs that are not directly accessed by your scripts in Project. This will allow your program to run in the editor.

When you build, again copy the dependency DLL files, this time to the root of the build directory (right next to the generated executable). This should allow your application to load them at runtime.

(Tip: you can use Dependency Walker look at you DLLs and see what they depends on.)

sirbrialliance
  • 3,612
  • 1
  • 25
  • 15
  • Just a note, if the dll is a managed assembly (assuming I have the terminology right) that has a separate assembly as a dependency, the first assembly can go in Plugins folder along with the dependency and work in a build. However for running in the editor, you need a copy of the dependency in the project folder like described above for dll's. – michael Mar 30 '20 at 19:10
2

Make sure the following chacklist is satisfied:

  • Plugins should all stay in a folder called Plugins.
  • The architecture your dll is built for (x86 or x86_64) must correspond to the architecture version of Unity Editor. Unity Editor 32-bit will not load 64 bit plugins and viceversa.
  • If you are targeting both 32 and 64 bit architectures you should put your dlls in special named folders inside the Plugins folder. The names are Plugins/x86 for 32 bit dlls and Plugins/x86_64 (x64 also works) for 64 bit dlls.
  • Visual C++ Redistributables must be installed. I have all from 2008.
  • When you build all your dlls should be copied into the root where your executable is (and again built for the correct x86/x64 architecture)

If you keep getting a namespace error it means the dll you are importing has unmanaged code and it must be wrapped into another managed dll Pugin in order to work.

These threads are a bit outdated but still relevant

DLLNotFoundException - Unity3D Plugin

Unity internal compiler error with custom dll

Steak Overflow
  • 7,041
  • 1
  • 37
  • 59
2

I spent one day with this error. My issue was that Android doesn't get the library and always get and DDLNotFound error. My solution was:

1.- Be sure that you have the libraries for the proper architecture in the Plugins folder.

Plugins/Android/x86 and Plugins/Android/armeabi-v7a if your build settings is FAT(x86&arm)

2.- Check that Unity recognizes them as libraries. If you select them in the Project tab you should see them as a library and the platform and architecture related.

3.- After the build (don't close Unity Editor!), you can check in the Temp/StagingArea/libs if your libraries are there. If there are there for sure the libraries are going to be in the APK. As a double check, you can open your APK (change to zip extension) and see the libraries in the lib folder.

4.- In C# you should remove any lib prefix in your library name, for example:

If your library name is "libdosomething.so" you should call it as

[DllImport ("dosomething")]

I hope this work for you :)

Cheers.

  • This helped me. I am using Unity 2018.3 and the proper architecture is now Plugins/Android_x86 and Plugins/Android_armeabi-v7a. I also put a library in Plugins/Android_arm64-v8a but while Unity recognises it as arm64 it is not used.. Android_x86_64 is not supported – Adrian G Feb 14 '19 at 10:09
1

In my case, I have DllNotFoundException: ovrplatiformloader

 Unity   : DllNotFoundException: ovrplatformloader
 Unity   :   at (wrapper managed-to-native) Oculus.Platform.CAPI.ovr_UnityInitWrapperAsynchronous(string)
 Unity   :   at Oculus.Platform.AndroidPlatform.AsyncInitialize (System.String appId) [0x00013] in <29065e843b82403894fca6c6f2974090>:0 
 Unity   :   at Oculus.Platform.Core.AsyncInitialize (System.String appId) [0x0004f] in <29065e843b82403894fca6c6f2974090>:0 
 Unity   :   at DBHelper.Start () [0x00019] in <29065e843b82403894fca6c6f2974090>:0 

My solution is:

  1. Re-import files that doesn't work (libovrplatformloader.so)
  2. Reconstruct the Platform/Plugins architecture. Old: Platform/Plugins/Android32/libovrplatformloader.so. New: Platform/Plugins/Android/x86/libovrplatformloader.so and Platform/Plugins/Android/armeabi-v7a/libovrplatformloader.so
  3. Modify the import setting of libovrplatformloader.so. Change any platform to only Android platform and enable 'load on startup' selection. Choose ARMv7 CPU in armeabit-v7a while choose x86 CPU in x86 folder.
cancan
  • 11
  • 1
0

just put the dlls under Plugins folder and that works for me

fieldChao
  • 176
  • 1
  • 1
  • 14
0

I was having the same issue, and the solutions described here didn't work. I think my case was a little different. I think that the .dll I was importing depended on other .dll files. So I imported the other files related to that .dll (which I thought were unnecessary since I am not calling them directly on c# code) and that solved the issue.

mvoelcker
  • 330
  • 4
  • 8