Replace magic offsets with proper offset calculation by lostmsu · Pull Request #1441 · pythonnet/pythonnet

@lostmsu

removed some macro-like method copy-pastes from CPython and bits of dead code

All Python types created to represent CLR concepts derive from `CLR MetaType` (as before), which now has two new fields:

- `tp_clr_inst_offset`, which is similar to `tp_dictoffset` in that it tells where to find `GCHandle` in instances of this type (e.g. where to find `GCHandle` pointing to `System.Uri` in corresponding Python object)
- `tp_clr_inst`, which holds an optional instance of `ManagedType`, that implements the behavior of the type itself (e.g. `GCHandle` pointing to `ClassObject(type = System.Uri)`)

So the layout of all Python types created by Python.NET is
  PyType type;
  nint tp_clr_inst_offset;
  GCHandel tp_clr_inst; (points, for example, to an instance of `ClassObject`)

When a Python type, that reflects CLR type is created, the layout of instances will be:
  BaseTypeFields base;
  optional (if not in base): IntPtr dict;
  optional (if not in base): IntPtr weaklist;
  GCHandle gcHandle; (points to `CLRObject` instance, which in turn, for example, points to the actual instance of `System.Uri`)

The offset to GC handle is recorded in the Python type's `tp_clr_inst_offset`, and can be found as `PyObject_Type(inst).tp_clr_inst_offset`. Or, preferably, accessor functions in `ManagedType` should be used.