My goal is to get a toy C++ library wrapped using SWIG, and accessible to C# / Mono scripts in Unity. (In other words, have the library functionality working in a Windows build of the game. I'll tackle Android next :)
I have been following a combination of Build a C# module (SWIG tutorial), Unity and DLLs (Eric Eastwood) and Getting started with SWiG for Visual Studio projects (Technical Recipes). I have generated two DLLs in Visual Studio 2013 and added them to the Unity project. But accessing the toy method at runtime is failing.
Steps I followed (including common fixes for the error I am receiving):
Create C++ project / custom build
- Create a C++ Win32 Console Application project in Visual Studio
- (because MonoDevelop on Windows cannot compile C++)
- Add example code to the project
- Create example.i (interface file for SWIG)
- Create an Custom Build Tool for the interface file
- Execute the Custom Build Tool (generates wrapper code for C++ and C#)
- Add C++ wrapper code to project (will be used later to generate C++ DLL)
Create C# project
- Create a C# Class Library project in Visual Studio
- Change Target Framework version 3.5
- Add C# wrapper code files to project root
- Add the following library references and namespace to the C# wrapper files:
using System;
using System.Runtime.InteropServices;
namespace CSharpExampleLib {
...
}
Build two Release DLLs
- Set the build settings to Release / x86 for both projects
- Set the target for the C# build to the target of the C++ build
- Build the solution (generates two DLLs, one per project)
- Confirm with Dependency Walker that the DLLs do not see each other as missing (reference)
- Used
CorFlags
to force the C# DLL to be 32-bit (reference) (this does not work / does not apply to C++ DLL)
Add DLLs to Unity project
- Create a new project in Unity 4 (Pro) with a simple Mono script
- Close Unity project
- Copy the DLLs into Assets/Plugins folder
- Reopen the Unity project (DLLs recognised)
- Right-click on Assets in the Project Hierarchy, select "Synch with MonoDevelop..." (opens simple script in MonoDevelop, ensures DLLs are accessible)
- Added library references to the simple script:
using System.Runtime.InteropServices;
using System.IO;
Invoke method from DLL
Finally, I added a logging call from the simple script to the C# DLL (Intellisense confirms that the DLL and method are accessible):
Debug.Log(CSharpExampleLib.example.fact(3));
// should log the result of 3 factorial
Runtime error
However, when I start the game from the Unity editor, I get the following error:
DllNotFoundException: example
CSharpExampleLib.examplePINVOKE+SWIGExceptionHelper..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for SWIGExceptionHelper
CSharpExampleLib.examplePINVOKE..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for CSharpExampleLib.examplePINVOKE
CSharpExampleLib.example.fact (Int32 n)
SimpleController.Start () (at Assets/scripts/SimpleController.cs:10)
I made several attempts to correct common causes for this error (build as Release, build as 32-bit, check Dependency Walker, etc) to no avail. Is there something SWIG- or Unity-specific I am missing? Any other checks I can perform on my DLLs?