Skip to content

Instantly share code, notes, and snippets.

@paulhayes
Last active February 21, 2024 14:00
Show Gist options
  • Save paulhayes/06435c009d8ae2d305cc7d9e2f6cc1b7 to your computer and use it in GitHub Desktop.
Save paulhayes/06435c009d8ae2d305cc7d9e2f6cc1b7 to your computer and use it in GitHub Desktop.
Runtime loading dlls in Unity3d
using System;
using UnityEngine;
public class DllLoadingAtRuntimeExample : MonoBehaviour
{
static IntPtr nativeLibraryPtr;
delegate int MultiplyFloat(float number, float multiplyBy);
delegate void DoSomething(string words);
void Awake()
{
if (nativeLibraryPtr != IntPtr.Zero) return;
nativeLibraryPtr = Native.LoadLibrary("MyNativeLibraryName");
if (nativeLibraryPtr == IntPtr.Zero)
{
Debug.LogError("Failed to load native library");
}
}
void Update()
{
Native.Invoke<DoSomething>(nativeLibraryPtr, "Hello, World!");
int result = Native.Invoke<int, MultiplyFloat>(nativeLibraryPtr, 10, 5); // Should return the number 50.
}
void OnApplicationQuit()
{
if (nativeLibraryPtr == IntPtr.Zero) return;
Debug.Log(Native.FreeLibrary(nativeLibraryPtr)
? "Native library successfully unloaded."
: "Native library could not be unloaded.");
}
}
/*
* Native dll invocation helper by Francis R. Griffiths-Keam
* www.runningdimensions.com/blog
*/
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public static class Native
{
public static T Invoke<T, T2>(IntPtr library, params object[] pars)
{
IntPtr funcPtr = GetProcAddress(library, typeof(T2).Name);
if (funcPtr == IntPtr.Zero)
{
Debug.LogWarning("Could not gain reference to method address.");
return default(T);
}
var func = Marshal.GetDelegateForFunctionPointer(GetProcAddress(library, typeof(T2).Name), typeof(T2));
return (T)func.DynamicInvoke(pars);
}
public static void Invoke<T>(IntPtr library, params object[] pars)
{
IntPtr funcPtr = GetProcAddress(library, typeof(T).Name);
if (funcPtr == IntPtr.Zero)
{
Debug.LogWarning("Could not gain reference to method address.");
return;
}
var func = Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(T));
func.DynamicInvoke(pars);
}
[DllImport("kernel32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
}
@paulhayes
Copy link
Author

🤯 Wow, that is incredible work. If I have any ideas I'll suggest them.

@plaidpants
Copy link

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment