Codecs: customizing object marshalling between .NET and Python - pythonnet/pythonnet GitHub Wiki
Codecs
Python.NET automatically does some conversions between .NET and Python. For example, when Python calls this C# method:
void Foo(int bar) { ... }
via Foo(42)
, Python value 42
of type int
will be automatically converted to .NET type System.Int32
. Another way to invoke those conversions is to call dotNetObject.ToPython()
(available as an extension method) or pyObject.As<T>()
to convert PyObject
to .NET.
An incomplete list of Python types, that are converted between Python and .NET automatically: most numeric types, bool
, string
, Nullable<T>
to its Value
or None
and back, .NET arrays to Python's list
and back, etc.
You can define your own conversions (codecs) by implementing one of the (or both) interfaces:
Python.Runtime.IPyObjectDecoder
to marshal Python objects to .NET
interface IPyObjectDecoder {
bool CanDecode(PyObject objectType, System.Type targetType);
bool TryDecode<T>(PyObject pyObj, out T value);
}
Python.Runtime.IPyObjectEncoder
to marshal .NET objects to Python
interface IPyObjectEncoder {
bool CanEncode(System.Type);
PyObject TryEncode(System.Object);
}
Once implemented, instances have to be registered with Python.Runtime.PyObjectConversions.RegisterEncoder
/-Decoder
. You can override some of the default conversions by registering new codec(s). In Python.NET 3+ most default conversions will be implemented as codecs, which you will have to register manually.
Codec priorities
When multiple codecs are registered, runtime will first try ones, that were registered earlier. If you need to have some grouping of codecs by priority, create and expose Python.Runtime.Codecs.EncoderGroup
/-.DecoderGroup
. For example:
public static EncoderGroup HighPriorityEncoders{ get; } = new EncoderGroup();
void Init() {
PyObjectConversions.RegisterEncoder(HighPriorityEncoders);
var lowPriorityEncoder = new SomeEncoder();
PyObjectConversions.RegisterEncoder(lowPriorityEncoder);
}
... some time later
HighPriorityEncoders.Add(new SomeOtherEncoder());