I am picking up a Unity project that I started back in 2017. Combined with this Unity project is a native library that I am building for iOS, Android, Windows, and MacOS.

I’m using C# as the scripting language for Unity and IL2CPP as the scripting backend.

Back in 2017, your C# code had to have different arguments to DllImport depending on the operating system.

On most systems, your code would look like this:

[DllImport("myNativeLib")]
public static extern void MyNativeLibInit();

[DllImport("myNativeLib")]
public static extern int MyNativeLibRandomInt();

But for iOS, it would look like this:

[DllImport("__Internal")]
public static extern void MyNativeLibInit();

[DllImport("__Internal")]
public static extern int MyNativeLibRandomInt();

Because iOS does not allow dynamic libraries, the "__Internal" hack tells IL2CPP to generate different code for static libraries on iOS.

I wanted to maintain the same code on all systems, so I kept [DllImport("myNativeLib")] on iOS.

The generated code from IL2CPP would generate an error on iOS:

DllNotFoundException: Unable to load DLL 'myNativeLib': The specified module could not be found.

So I wrote a tool (small Python script) that would :

  1. Read in Bulk_XXXUnity_0.cpp
  2. Find these strings for native functions: // Native function invocation
  3. Convert all of these functions to use the static library function calls

Any way, all of this was working back in 2017.

I downloaded and installed a new version of Unity from 2020 and went spelunking into the generated .cpp code for newer versions of Unity and was pleasantly surprised.

I don’t need the staticizer tool any more!

Just define:

FORCE_PINVOKE_xxx_INTERNAL=1

For example, in your Xcode project:

Project > Unity-iPhone

Build Settings

Apple Clang - Preprocessing > Preprocessor Macros:

FORCE_PINVOKE_xxx_INTERNAL=1

This makes iOS development much easier.

Thanks Unity devs!

Updated: