public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
ClassObject self = GetManagedObject(tp) as ClassObject;
// Sanity check: this ensures a graceful error if someone does
// something intentially wrong like use the managed metatype for
// a class that is not really derived from a managed class.
if (self == null) {
return Exceptions.RaiseTypeError("invalid object");
}
Type type = self.type;
// Primitive types do not have constructors, but they look like
// they do from Python. If the ClassObject represents one of the
// convertible primitive types, just convert the arg directly.
if (type.IsPrimitive || type == typeof(String)) {
if (Runtime.PyTuple_Size(args) != 1) {
Exceptions.SetError(Exceptions.TypeError,
"no constructors match given arguments"
);
return IntPtr.Zero;
}
IntPtr op = Runtime.PyTuple_GetItem(args, 0);
Object result;
if (!Converter.ToManaged(op, type, out result, true)) {
return IntPtr.Zero;
}
return CLRObject.GetInstHandle(result, tp);
}
if (type.IsAbstract) {
Exceptions.SetError(Exceptions.TypeError,
"cannot instantiate abstract class"
);
return IntPtr.Zero;
}
if (type.IsEnum) {
Exceptions.SetError(Exceptions.TypeError,
"cannot instantiate enumeration"
);
return IntPtr.Zero;
}
Object obj = self.binder.InvokeRaw(IntPtr.Zero, args, kw);
if (obj == null) {
// It is possible for __new__ to be invoked on construction
// of a Python subclass of a managed class, so args may
// reflect more args than are required to instantiate the
// class. So if we cant find a ctor that matches, we'll see
// if there is a default constructor and, if so, assume that
// any extra args are intended for the subclass' __init__.
IntPtr eargs = Runtime.PyTuple_New(0);
obj = self.binder.InvokeRaw(IntPtr.Zero, eargs, kw);
Runtime.Decref(eargs);
if (obj == null) {
return IntPtr.Zero;
}
}
return CLRObject.GetInstHandle(obj, tp);
}