C#: Platform Invoke (P/Invoke)
What is Platform Invoke (P/Invoke) in C#?
One of the features of C# is native interoperability. P/Invoke allows you to call native libraries (unmanaged code) from C# (managed code). An example by Microsoft shows how you can call the MessageBox
function in user32.dll
library:
using System;
using System.Runtime.InteropServices;
public class Program
{
// Import user32.dll (containing the function we need) and define
// the method corresponding to the native function.
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);
public static void Main(string[] args)
{
// Invoke the function as a regular managed method.
MessageBox(IntPtr.Zero, "Command-line message box", "Attention!", 0);
}
}
How to wrap unmanaged code with P/Invoke?
An example of unmanaged code is a third party dynamic library written in C or C++. In this scenario, let’s say we have a cross-platform library called MyLibrary
. We are also going to assume we have binaries for Windows, Linux and MacOS:
MyLibrary.dll
libMyLibrary.so
libMylibrary.dylib
Next, let’s expose the void DoSomeWork(int a, char* b)
function in our potential example. We can use the DLLImport
attribute to define our function and how it should be executed:
using System;
using System.Runtime.InteropServices;
// We create a static class with the same name as our library
public static class MyLibrary
{
// Key things to note about this function:
// 1 - You only need the name of the library, no need for OS prefixes or suffixes
// 2 - We need a 8-bit null terminated string, so make sure to set the correct CharSet
[DllImport("MyLibrary", CharSet=CharSet.Ansii)]
public static extern void DoSomeWork(int a, string b)
}
Warning
For best practices, look at Microsoft’s Native interoperability best practices page. The links are provided below.
How to call wrapped unmanaged code with P/Invoke?
Assuming you have finished writing your wrapper, all you have to do is call your static class function from within your code.
public class MyClass
{
public MyClass(int number)
{
// We are going to call our library in this constructor
MyLibrary.DoSomeWork(number, "MyClass(" + number + ")");
}
}
Note
If using these functions in Nominal Editor, make sure to manually add the native C++ DLLs to the Mono folder inside the Scripts
directory. This will ensure the Mono system is able to find the native unmanaged libraries.
Useful Resources
For more information on P/Invoke, have a look at the links below from Microsoft Learn: