P/Invoke to dynamically loaded library on Mono

后端 未结 4 898

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:02

    I needed to load a native library extracted to a temporary location, and I almost found a solution. I've checked Mono's source code and figured out a way:

    [DllImport("__Internal", CharSet = CharSet.Ansi)]
    private static extern void mono_dllmap_insert(IntPtr assembly, string dll, string func, string tdll, string tfunc);
    
    // and then somewhere:
    mono_dllmap_insert(IntPtr.Zero, "somelib", null, "/path/to/libsomelib.so", null);
    

    This kind of works. The problem is, you cannot allow Mono's stupid JIT compiler to catch a whiff of any DllImported method referring this library before calling mono_dllmap_insert().

    Because if it does, strange things will happen:

    Mono: DllImport searching in: '/tmp/yc1ja5g7.emu/libsomelib.so' ('/tmp/yc1ja5g7.emu/libsomelib.so').
    Mono: Searching for 'someGreatFunc'.
    Mono: Probing 'someGreatFunc'.
    Mono: Found as 'someGreatFunc'.
    Error. ex=System.DllNotFoundException: somelib
    

    So now that I'm calling my native someGreatFunc(), Mono is able to find the library and load it (I checked), it is able to find the symbol (I checked), but because somewhen in the past when it was doing JIT it was not able to load that library, it decides to throw DllNotFoundException anyway. I guess the generated code contains a hardcoded throw statement or something :-O

    When you call another native function from the same library that happens not to have been JITted before you called mono_dllmap_insert(), it will work.

    So you can either use the manual solution added by @gordonmleigh or you must tell Mono where the library is BEFORE it JITs any of these imports. Reflection may help there.

提交回复
热议问题