I\'m writing a cross-platform .NET library that uses some unmanaged code. In the static constructor of my class, the platform is detected and the appropriate unmanaged library
After much searching and head-scratching, I've discovered a solution. Full control can be exercised over the P/Invoke process by using dynamic P/Invoke to tell the runtime exactly where to find the code.
Edit:
You need these imports:
[DllImport("kernel32.dll")]
protected static extern IntPtr LoadLibrary(string filename);
[DllImport("kernel32.dll")]
protected static extern IntPtr GetProcAddress(IntPtr hModule, string procname);
The unmanaged library should be loaded by calling LoadLibrary
:
IntPtr moduleHandle = LoadLibrary("path/to/library.dll");
Get a pointer to a function in the dll by calling GetProcAddress
:
IntPtr ptr = GetProcAddress(moduleHandle, methodName);
Cast this ptr
to a delegate of type TDelegate
:
TDelegate func = Marshal.GetDelegateForFunctionPointer(
ptr, typeof(TDelegate)) as TDelegate;
Use these imports:
[DllImport("libdl.so")]
protected static extern IntPtr dlopen(string filename, int flags);
[DllImport("libdl.so")]
protected static extern IntPtr dlsym(IntPtr handle, string symbol);
const int RTLD_NOW = 2; // for dlopen's flags
Load the library:
IntPtr moduleHandle = dlopen(modulePath, RTLD_NOW);
Get the function pointer:
IntPtr ptr = dlsym(moduleHandle, methodName);
Cast it to a delegate as before:
TDelegate func = Marshal.GetDelegateForFunctionPointer(
ptr, typeof(TDelegate)) as TDelegate;
For a helper library that I wrote, see my GitHub.