Error loading library from Unity

Issue #19 resolved
Blair Ahlquist created an issue

I have been using AssimpNet 3.3.2 from within Unity successfully. I transferred my projects from .Net Framework 4.7.1 to .Net Standard 2.0 and found that AssimNet 3.3.2 wasn't compatible with .Net Standard, so I tried the release candidate 4.1.0-rc1. My first call into Assimp results in a NotImplementedException:

System.NotImplementedException: The method or operation is not implemented. at System.Runtime.InteropServices.Marshal.GetHRForLastWin32Error () [0x00000] in <f2e6809acb14476a81f399aeb800f8f2>:0 at Assimp.Unmanaged.UnmanagedLibrary+UnmanagedWindowsLibraryImplementation.NativeLoadLibrary (System.String path) [0x00011] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.Unmanaged.UnmanagedLibrary+UnmanagedLibraryImplementation.LoadLibrary (System.String path) [0x00008] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.Unmanaged.UnmanagedLibrary.LoadLibrary (System.String libPath) [0x00025] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.Unmanaged.UnmanagedLibrary.LoadLibrary () [0x00016] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.Unmanaged.UnmanagedLibrary.LoadIfNotLoaded () [0x00023] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.Unmanaged.AssimpLibrary.CreatePropertyStore () [0x00000] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.AssimpContext.CreateConfigs () [0x00006] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.AssimpContext.PrepareImport () [0x00000] in <1810b14227374941b373fe3bb5771dc4>:0 at Assimp.AssimpContext.ImportFile (System.String file, Assimp.PostProcessSteps postProcessFlags) [0x00044] in <1810b14227374941b373fe3bb5771dc4>:0

Comments (4)

  1. Nicholas Woodfield repo owner

    If the NativeLoadLibrary function failed to load the native DLL, it'll attempt to get an error code from windows. I know in Mono this function is not implemented, although with Unity3D supporting net standard, I wouldn't expect this function to throw (guess I'm wrong, I assume you switched the scripting backend to netstandard 2.0?).

    Please use the RC2 nuget package as you'll hit some issues with animations in RC1 if you import animated models. I'll push a small change to make sure this not implemented exception doesn't obfuscate the AssimpException you'll get when the native library fails to load.

    Please verify the native DLL is where the AssimpLibrary expects it at runtime (either defaults are used, or you set the DLL locations when initializing the singleton). The nuget package has a msbuild targets file that is similar in 3.3.2 that copies the native DLLs to the output directory. Make sure that's being invoked.

  2. cassidy hilts

    I'm having the same problem here, and can confirm the scripting backend is .NET standard 2.0. I have the 4.1.0 native DLL installed, however I'm not sure if it's in the correct place and could not find in the documentation how to specify the location of the native DLL. EDIT: Fixed for unity, the DLL should be placed into the Unity/Editor directory when running from editor and the build directory when the project is built.

  3. Nicholas Woodfield repo owner

    @cassidy20Below

    So I've been tinkering with Unity, and it's highly dependent on how users setup their project (which I always suspected).

    In non-unity projects, the intention is that the native DLL is loaded relative to the managed DLL, usually the base directory of the application. By default, it looks in the same folder. This is also why each native DLL is uniquely named, and the msbuild script outputs to the same target folder as the managed DLL.

    From what I can tell, out of the box, unity will treat the native DLL as an asset and does not copy it to the same folder with the managed DLL. And because the scripts are run in-process, the application base directory is that Unity/Editor folder. And in standalone, the native DLL will be in a separate folder from the managed DLL, so the assumption of the library breaks down in both cases.

    The best solution, IMO, is to have a script that will do a one-time initialization whether run in editor or standalone. That would involve you probing for the native DLLs (in whatever folder setup you created in your assets), and calling AssimpLibrary.Instance.LoadLibrary(pathToDLL). If the native DLL isn't loaded, the first time you make a call into assimp, this function is called with the default path mentioned above.

    There are two things I'm planning on doing before the next official release:

    1. Implement better probing logic for the native DLLs and refactor how the native DLLs get deployed. It looks like the best practice for Nuget packages now is to have a "runtimes" folder (https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks). Since I'm supporting more platforms out of the box now, copying all those unmanaged DLLs blindly, the output folder is getting bloated, and since Nuget has architecture-specific folders the library can just load the DLLs in the nuget cache.

    2. Ship a unity-specific initialization script, and bundle it up w/ the library as a Unity plugin and put it on the asset store. The script should be fairly simple and resolve based on platform to the correct asset folder.

  4. Nicholas Woodfield repo owner

    I have completed the above two tasks. In the build output of the AssimpNet project, there is now a folder called "UnityPlugin", the contents is a "Plugins" folder that you can drag/drop right into the "Assets" folder in the Unity3D editor.

    This will add an AssimpNet plugin folder, with a folder structure for linux/macos/windows binaries, and a single Unity script called "AssimpUnity". At runtime initialization, it will attempt to resolve the native binaries and provide the correct names/probing paths to AssimpLibrary. I've tested it both running from within the editor, and standalone (on Windows and MacOS).

    I'll be publishing this as a unity package on the asset store. Essentially it's a unity-specific nuget package.

  5. Log in to comment