Usage¶
Getting a runtime¶
To get a Runtime
instance, one of the get_*
functions has to be
called. There are currently the factory functions get_mono()
,
get_coreclr()
and get_netfx()
. All of these provide various
configuration options that are documented in the Reference.
They also provide reasonable defaults and can be called without parameters if
the respective runtime is installed globally:
from clr_loader import get_coreclr
runtime = get_coreclr()
After this, the runtime will usually already be initialized. The initialization is delayed for .NET Core to allow adjusting the runtime properties beforehand.
Information on the runtime, its version and parameters can be retrieved using
runtime.info()
(see Runtime.info()
).
Getting a callable function¶
A wrapped assembly can be retrieved from the runtime by calling
Runtime.get_assembly()
with the path.
The following example class is provided in the repository:
using System.Text;
using System.Runtime.InteropServices;
using System;
namespace Example
{
public class TestClass
{
public static int Test(IntPtr arg, int size) {
var buf = new byte[size];
Marshal.Copy(arg, buf, 0, size);
var bufAsString = Encoding.UTF8.GetString(buf);
var result = bufAsString.Length;
Console.WriteLine($"Called {nameof(Test)} in {nameof(TestClass)} with {bufAsString}, returning {result}");
Console.WriteLine($"Binary data: {Convert.ToBase64String(buf)}");
return result;
}
}
}
Assuming it has been compiled to out/example.dll
, it can now be loaded using
Runtime.get_assembly()
:
assembly = runtime.get_assembly("path/to/assembly.dll")
Note
This does not guarantee that the DLL is already loaded and will not necessarily trigger an error if that is not possible. Actually resolving the DLL only happens (for all implementations but Mono) when retrieving the concrete function.
The assembly
instance can now be used to get a wrapper instance of the
Test
function in Python. The given parameters are the fully qualified class
name and the function name. Alternatively, a single parameter can be provided,
and we assume that the last “component” is the function name. These are
equivalent:
function = assembly.get_function("Example.TestClass", "Test")
function = assembly.get_function("Example.TestClass.Test")
This function can now be called with a Python binary
like this:
result = function(b"testy mctestface")
The IntPtr
parameter in C# will now point directly at the binary
buffer,
the int
parameter will contain the size. The given call will thus result in
the output:
Called Test in TestClass with testy mctestface, returning 16
Binary data: dGVzdHkgbWN0ZXN0ZmFjZQ==
result
will now be 16
.
Warning
While the buffer can theoretically also be changed in the .NET function, this is not tested.