You can use native code in Unity by importing Native Plugins.
Native Plugins are basically libraries of native code written in C/C++. You can import them in C# and make function calls to native code. This way you can gain performance, or use them for whatever reasons you have. I want to note that this isn’t Unity specific thing, I am just using Unity as an example.
How To Create a Native Library
I am working with Visual Studio, so I will show you how to do it in Visual Studio.
You need to create a C++ Dynamic-Link Library (DLL) project. After you write your native code there, you need to build the project and a .dll will be generated. Later you will need to import this .dll in Unity.
Let’s write a simple function so that I can show you how to import it in Unity.
#define DllExport __declspec(dllexport) extern "C" { DllExport float GetFloat() { return 1.0f; } }
How To Import It In Unity
First you have to place the .dll somewhere in the Assets folder. You can create a sub-folder specifically fot the native libraries if you want, it doesn’t matter. Let’s say the name of the library is MyLib.dll. This is how you import it.
public class TestBehaviour : MonoBehaviour { [DllImport("MyLib")] private static extern float GetFloat(); private void Awake() { Debug.Log(GetFloat()); } }
How To Import a Class
Lets say you don’t want to import static functions, but an entire class with instance methods instead.
The concept of “instance” method is actually just some sugar that the compiler/framework provides. Actually all methods are static. Instance methods just have an additional hidden parameter “this” that is a reference to the object instance.
If you want to call a native method for a certain native object, you would need to pass the native object reference along to the method call. Usually, you would create a wrapper class in .NET/C# that holds that native pointer (IntPtr) and provides the required methods for the C# environment. Those calls are then forwarded to the native interface. You just have to pass the object along.
Here is an example
// Header class Person { public: Person(const char* name); ~Person(); const char* GetName() const; private: char* _name; };
// Source Person::Person(const char* name) { size_t nameLength = strlen(name); _name = new char[nameLength + 1]; for (int i = 0; i < nameLength; i++) { _name[i] = name[i]; } _name[nameLength] = '\0'; } Person::~Person() { delete _name; _name = nullptr; } const char* Person::GetName() const { return _name; }
// Export Interface extern "C" { DllExport Person* CreatePerson(const char* name) { return new Person(name); } DllExport void DestroyPerson(Person* person) { delete person; } DllExport const char* GetPersonName(Person* person) { return person->GetName(); } }
// C# Wrapper Class public class Person { private IntPtr _personPtr = IntPtr.Zero; public Person(string name) { IntPtr namePtr = Marshal.StringToHGlobalAnsi(name); _personPtr = CreatePerson(namePtr); Marshal.FreeHGlobal(namePtr); } ~Person() { if (_personPtr != IntPtr.Zero) { DestroyPerson(_personPtr); _personPtr = IntPtr.Zero; } } public string GetName() { IntPtr namePtr = GetPersonName(_personPtr); string name = Marshal.PtrToStringAnsi(namePtr); return name; } [DllImport("MyLib")] private static extern IntPtr CreatePerson(IntPtr name); [DllImport("MyLib")] private static extern void DestroyPerson(IntPtr person); [DllImport("MyLib")] private static extern IntPtr GetPersonName(IntPtr person); }
Hello Denis, thank you for this useful article.
I have a question, using Unity under Windows 10 i am trying to find the best way to use some WPF functions that could be useful, that is not about UI or Xaml, more about BitmapImage and image manipulation.
Since those assemblies are not mono-compatible i was thinking of building a bridge using a native DLL.
One of the first question is: if i build a DLL with C++/CLI (so a native managed assembly!) that uses WPF functions, would that work in your opinion?
If that’s not possibile, how would you bridge a normal native C++ dll to call managed WPF functions?
Quite an advanced topic I know.. thank you for your time!
Stefano
I don’t think it will work. You can create a bridge, but you are still going to make calls to managed WPF functions, which are still not mono-compatible. Haven’t tried anything like this to be honest. I checked some article here. It’s worth checking. I also made a quick search to see if WPF has C++ API, but it doesn’t unfortunately. What exactly do you want to do with Bitmaps? If you want to use bitmap fonts I can suggest you this
Thank you Denis,
WPF has some utilities i couldn’t find anywhere, namely, the ability to load an image at a lower resolution directly from disk without loading the _entire_ image in memory.
Let’s say you have a 1TB Png, and you want to create a thumbnail of 64 pixels (absurd i know), the Unity code i have would need 1TB or more of RAM because needs to load it upfront.
With WPF and BitmapImage.DecodePixelHeight you have exactly this feature.
https://docs.microsoft.com/en-us/dotnet/api/system.windows.media.imaging.bitmapimage.decodepixelheight?view=netframework-4.7.2
Probably it uses WIC in c++, but it is rather complicated and couldn’t find any sample c++ code with that functionality to wrap into a unmanaged dll.
I also thought about spawning a ffmpeg to create the thumbnail, that is a workaround that complicates the task a lot.
I think you can set the maximum size of a texture in the texture importer. Check this. Search for **Max Size**. I think it actually reduces the size of a texture in a build. Check this documentation
That works for assets in the build, but i need to load images at runtime from the filesystem.
I see. Well, good luck mate 🙂
I will make it, and let you know 😉