Table of Contents

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: