P/Invoke to dynamically loaded library on Mono

后端 未结 4 896

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

4条回答
  •  [愿得一人]
    2021-02-02 01:08

    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:

    Windows solution

    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;
    

    Linux Solution

    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.

提交回复
热议问题