Search code examples
c#linux.net-coredlopengarrys-mod

How to make a dotnet core library loadable from dlopen on unix system


so I'm going to be making a gmod module to async a few tasks and generally make the server run better and faster.

I want to make this in c# (so I don't have to write up a large cross-platform wrapper, and it doesn't take hours to write what 20 minutes can do in c#) but I don't know any cross-platform library that supports native loading and native exports. I know that DllExport works but only for windows .Net Framework and not Linux or even just dotnet core without a custom coreclr.

[DllExport("gmod13_close", CallingConvention = CallingConvention.Cdecl)]
public static Int32 Close(IntPtr LuaBasePtr)
{
    return 0;
}
[DllExport("gmod13_open", CallingConvention = CallingConvention.Cdecl)]
public static Int32 Open(lua_State LuaState)
{
    return 0;
}

if it is not possible to enable it to be loaded by dlopen directly without some workaround, what's the workaround I can get by just using that.


Solution

  • You cannot write a C-compatible shared library directly in .NET on a Unix system. C#, like other .NET languages, is managed code: it has a garbage collector and an interpreted runtime. In order to write a dynamically loadable module usable on Linux, you'd need to write in a language that compiles to machine code (e.g., C, C++, or Rust) or use wrapper code that starts the .NET runtime and invokes the function you want to call. This may happen to work on Windows due to COM, but it won't on Unix or Linux.

    For similar reasons, it isn't possible to do this with Java, either, unless you're using something like GCJ that compiles to native code.

    In general, .NET is not a good environment if you're trying to target Linux systems because it isn't designed to work well there (it does work, but it integrates poorly) and different distros include different runtimes (Mono vs. .NET Core). Users are also not likely to have it installed and therefore it generally adds a large (and often undesired) dependency to your software.

    If you really want to do this, there is example code for doing something like this in the CoreCLR tree. Note that this depends on .NET Core, so it won't work on Mono, and therefore won't work on Debian or Ubuntu without additional software.