[Zope-CVS] CVS: PythonNet/src/runtime - Interop.cs:1.1 ClassBase.cs:1.4 ClassObject.cs:1.5 Exceptions.cs:1.5 ManagedType.cs:1.2 MetaType.cs:1.5 MethodWrapper.cs:1.2 NativeCall.cs:1.2 Runtime.cs:1.6 TypeManager.cs:1.6 CallbackThunks.cs:NONE

Brian Lloyd brian at zope.com
Fri Aug 8 16:50:01 EDT 2003


Update of /cvs-repository/PythonNet/src/runtime
In directory cvs.zope.org:/tmp/cvs-serv22496/src/runtime

Modified Files:
	ClassBase.cs ClassObject.cs Exceptions.cs ManagedType.cs 
	MetaType.cs MethodWrapper.cs NativeCall.cs Runtime.cs 
	TypeManager.cs 
Added Files:
	Interop.cs 
Removed Files:
	CallbackThunks.cs 
Log Message:
checkpoint

=== Added File PythonNet/src/runtime/Interop.cs ===
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.

using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Reflection;

namespace Python.Runtime {

    // This file defines objects to support binary interop with the Python
    // runtime. Generally, the definitions here need to be kept up to date
    // when moving to new Python versions.


    [Serializable()]
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Delegate)]
    internal class CallConvCdeclAttribute : Attribute {
	public CallConvCdeclAttribute() {}
    }


    [Serializable()]
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Delegate)]
    internal class PythonMethodAttribute : Attribute {
	public PythonMethodAttribute() {}
    }


    // This class defines the in-memory layout of instances of all managed 
    // classes and subclasses of managed classes. Because we do not allow
    // multiple inheritance from managed classes, we are always in control
    // of the object layout.

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    internal class PyObjectHead {
	public IntPtr ob_refcnt = IntPtr.Zero;
	public IntPtr ob_type = IntPtr.Zero;
	public IntPtr ob_data = IntPtr.Zero;
	public IntPtr ob_dict = IntPtr.Zero;
    }


    // This class protects the rest of the code from having to deal with
    // PyObject * offsets directly, makes the code clearer and prevents 
    // bugs caused by bad offset caculation :)

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    internal class ObjectOffset {

	static ObjectOffset() {
	    int size = IntPtr.Size;
	    ob_refcnt = 0;
	    ob_type = 1 * size;
	    ob_data = 2 * size;
	    ob_dict = 3 * size;
	}

	public static int ob_refcnt;
	public static int ob_type;
	public static int ob_data;
	public static int ob_dict;
    }


    // This class is a managed representation of the in-memory layout of a
    // Python type object. This must be kept in sync with the definition in
    // object.h when making changes to support new Python versions.

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    internal class PyTypeObject {
	public IntPtr ob_refcnt = IntPtr.Zero;
	public IntPtr ob_type = IntPtr.Zero;
	public IntPtr ob_size = IntPtr.Zero;
	public IntPtr tp_name = IntPtr.Zero;
	public IntPtr tp_basicsize = IntPtr.Zero;
	public IntPtr tp_itemsize = IntPtr.Zero;
	public IntPtr tp_dealloc = IntPtr.Zero;
	public IntPtr tp_print = IntPtr.Zero;
	public IntPtr tp_getattr = IntPtr.Zero;
	public IntPtr tp_setattr = IntPtr.Zero;
	public IntPtr tp_compare = IntPtr.Zero;
	public IntPtr tp_repr = IntPtr.Zero;
	public IntPtr tp_as_number = IntPtr.Zero;
	public IntPtr tp_as_sequence = IntPtr.Zero;
	public IntPtr tp_as_mapping = IntPtr.Zero;
	public IntPtr tp_hash = IntPtr.Zero;
	public IntPtr tp_call = IntPtr.Zero;
	public IntPtr tp_str = IntPtr.Zero;
	public IntPtr tp_getattro = IntPtr.Zero;
	public IntPtr tp_setattro = IntPtr.Zero;
	public IntPtr tp_as_buffer = IntPtr.Zero;
	public IntPtr tp_flags = IntPtr.Zero;
	public IntPtr tp_doc = IntPtr.Zero;
	public IntPtr tp_traverse = IntPtr.Zero;
	public IntPtr tp_clear = IntPtr.Zero;
	public IntPtr tp_richcompare = IntPtr.Zero;
	public IntPtr tp_weaklistoffset = IntPtr.Zero;
	public IntPtr tp_iter = IntPtr.Zero;
	public IntPtr tp_iternext = IntPtr.Zero;
	public IntPtr tp_methods = IntPtr.Zero;
	public IntPtr tp_members = IntPtr.Zero;
	public IntPtr tp_getset = IntPtr.Zero;
	public IntPtr tp_base = IntPtr.Zero;
	public IntPtr tp_dict = IntPtr.Zero;
	public IntPtr tp_descr_get = IntPtr.Zero;
	public IntPtr tp_descr_set = IntPtr.Zero;
	public IntPtr tp_dictoffset = IntPtr.Zero;
	public IntPtr tp_init = IntPtr.Zero;
	public IntPtr tp_alloc = IntPtr.Zero;
	public IntPtr tp_new = IntPtr.Zero;
	public IntPtr tp_free = IntPtr.Zero;
	public IntPtr tp_is_gc = IntPtr.Zero;
	public IntPtr tp_bases = IntPtr.Zero;
	public IntPtr tp_mro = IntPtr.Zero;
	public IntPtr tp_cache = IntPtr.Zero;
	public IntPtr tp_subclasses = IntPtr.Zero;
	public IntPtr tp_weaklist = IntPtr.Zero;

	public IntPtr nb_add = IntPtr.Zero;
	public IntPtr nb_subtract = IntPtr.Zero;
	public IntPtr nb_multiply = IntPtr.Zero;
	public IntPtr nb_divide = IntPtr.Zero;
	public IntPtr nb_remainder = IntPtr.Zero;
	public IntPtr nb_divmod = IntPtr.Zero;
	public IntPtr nb_power = IntPtr.Zero;
	public IntPtr nb_negative = IntPtr.Zero;
	public IntPtr nb_positive = IntPtr.Zero;
	public IntPtr nb_absolute = IntPtr.Zero;
	public IntPtr nb_nonzero = IntPtr.Zero;
        public IntPtr nb_invert = IntPtr.Zero;
	public IntPtr nb_lshift = IntPtr.Zero;
	public IntPtr nb_rshift = IntPtr.Zero;
	public IntPtr nb_and = IntPtr.Zero;
	public IntPtr nb_xor = IntPtr.Zero;
	public IntPtr nb_or = IntPtr.Zero;
        public IntPtr nb_coerce = IntPtr.Zero;
	public IntPtr nb_int = IntPtr.Zero;
	public IntPtr nb_long = IntPtr.Zero;
	public IntPtr nb_float = IntPtr.Zero;
	public IntPtr nb_oct = IntPtr.Zero;
	public IntPtr nb_hex = IntPtr.Zero;
	public IntPtr nb_inplace_add = IntPtr.Zero;
	public IntPtr nb_inplace_subtract = IntPtr.Zero;
	public IntPtr nb_inplace_multiply = IntPtr.Zero;
	public IntPtr nb_inplace_divide = IntPtr.Zero;
	public IntPtr nb_inplace_remainder = IntPtr.Zero;
	public IntPtr nb_inplace_power = IntPtr.Zero;
	public IntPtr nb_inplace_lshift = IntPtr.Zero;
	public IntPtr nb_inplace_rshift = IntPtr.Zero;
	public IntPtr nb_inplace_and = IntPtr.Zero;
	public IntPtr nb_inplace_xor = IntPtr.Zero;
	public IntPtr nb_inplace_or = IntPtr.Zero;
	public IntPtr nb_floor_divide = IntPtr.Zero;
	public IntPtr nb_true_divide = IntPtr.Zero;
	public IntPtr nb_inplace_floor_divide = IntPtr.Zero;
	public IntPtr nb_inplace_true_divide = IntPtr.Zero;

	public IntPtr sq_length = IntPtr.Zero;
	public IntPtr sq_concat = IntPtr.Zero;
	public IntPtr sq_repeat = IntPtr.Zero;
	public IntPtr sq_item = IntPtr.Zero;
	public IntPtr sq_slice = IntPtr.Zero;
	public IntPtr sq_ass_item = IntPtr.Zero;
	public IntPtr sq_ass_slice = IntPtr.Zero;
	public IntPtr sq_contains = IntPtr.Zero;
	public IntPtr sq_inplace_concat = IntPtr.Zero;
	public IntPtr sq_inplace_repeat = IntPtr.Zero;

	public IntPtr mp_length = IntPtr.Zero;
	public IntPtr mp_subscript = IntPtr.Zero;
	public IntPtr mp_ass_subscript = IntPtr.Zero;

	public IntPtr bf_getreadbuffer = IntPtr.Zero;
	public IntPtr bf_getwritebuffer = IntPtr.Zero;
	public IntPtr bf_getsegcount = IntPtr.Zero;
	public IntPtr bf_getcharbuffer = IntPtr.Zero;
    }


    // This class protects the rest of the code from having to deal with
    // PyTypeObject offsets directly, makes the code clearer and prevents 
    // bugs caused by bad offset caculation :)

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    internal class TypeOffset {

	static TypeOffset() {
	    Type type = typeof(TypeOffset);
	    FieldInfo[] fi = type.GetFields();
	    int size = IntPtr.Size;
	    for (int i = 0; i < fi.Length; i++) {
		fi[i].SetValue(null, i * size);
	    }
	}

	public static int ob_refcnt = 0;
	public static int ob_type = 0;
	public static int ob_size = 0;
	public static int tp_name = 0;
	public static int tp_basicsize = 0;
	public static int tp_itemsize = 0;
	public static int tp_dealloc = 0;
	public static int tp_print = 0;
	public static int tp_getattr = 0;
	public static int tp_setattr = 0;
	public static int tp_compare = 0;
	public static int tp_repr = 0;
	public static int tp_as_number = 0;
	public static int tp_as_sequence = 0;
	public static int tp_as_mapping = 0;
	public static int tp_hash = 0;
	public static int tp_call = 0;
	public static int tp_str = 0;
	public static int tp_getattro = 0;
	public static int tp_setattro = 0;
	public static int tp_as_buffer = 0;
	public static int tp_flags = 0;
	public static int tp_doc = 0;
	public static int tp_traverse = 0;
	public static int tp_clear = 0;
	public static int tp_richcompare = 0;
	public static int tp_weaklistoffset = 0;
	public static int tp_iter = 0;
	public static int tp_iternext = 0;
	public static int tp_methods = 0;
	public static int tp_members = 0;
	public static int tp_getset = 0;
	public static int tp_base = 0;
	public static int tp_dict = 0;
	public static int tp_descr_get = 0;
	public static int tp_descr_set = 0;
	public static int tp_dictoffset = 0;
	public static int tp_init = 0;
	public static int tp_alloc = 0;
	public static int tp_new = 0;
	public static int tp_free = 0;
	public static int tp_is_gc = 0;
	public static int tp_bases = 0;
	public static int tp_mro = 0;
	public static int tp_cache = 0;
	public static int tp_subclasses = 0;
	public static int tp_weaklist = 0;

	public static int nb_add = 0;
	public static int nb_subtract = 0;
	public static int nb_multiply = 0;
	public static int nb_divide = 0;
	public static int nb_remainder = 0;
	public static int nb_divmod = 0;
	public static int nb_power = 0;
	public static int nb_negative = 0;
	public static int nb_positive = 0;
	public static int nb_absolute = 0;
	public static int nb_nonzero = 0;
        public static int nb_invert = 0;
	public static int nb_lshift = 0;
	public static int nb_rshift = 0;
	public static int nb_and = 0;
	public static int nb_xor = 0;
	public static int nb_or = 0;
        public static int nb_coerce = 0;
	public static int nb_int = 0;
	public static int nb_long = 0;
	public static int nb_float = 0;
	public static int nb_oct = 0;
	public static int nb_hex = 0;
	public static int nb_inplace_add = 0;
	public static int nb_inplace_subtract = 0;
	public static int nb_inplace_multiply = 0;
	public static int nb_inplace_divide = 0;
	public static int nb_inplace_remainder = 0;
	public static int nb_inplace_power = 0;
	public static int nb_inplace_lshift = 0;
	public static int nb_inplace_rshift = 0;
	public static int nb_inplace_and = 0;
	public static int nb_inplace_xor = 0;
	public static int nb_inplace_or = 0;
	public static int nb_floor_divide = 0;
	public static int nb_true_divide = 0;
	public static int nb_inplace_floor_divide = 0;
	public static int nb_inplace_true_divide = 0;

	public static int sq_length = 0;
	public static int sq_concat = 0;
	public static int sq_repeat = 0;
	public static int sq_item = 0;
	public static int sq_slice = 0;
	public static int sq_ass_item = 0;
	public static int sq_ass_slice = 0;
	public static int sq_contains = 0;
	public static int sq_inplace_concat = 0;
	public static int sq_inplace_repeat = 0;

	public static int mp_length = 0;
	public static int mp_subscript = 0;
	public static int mp_ass_subscript = 0;

	public static int bf_getreadbuffer = 0;
	public static int bf_getwritebuffer = 0;
	public static int bf_getsegcount = 0;
	public static int bf_getcharbuffer = 0;
    }


    // Managed representation of PyTypeFlags. It is actually more convenient
    // to have this as a class than an enum, as the enum requires boxing and
    // casting just to do a simple flag mask check.

    internal class TypeFlags {
	public static int HaveGetCharBuffer = (1 << 0);
	public static int HaveSequenceIn = (1 << 1);
	public static int GC = 0;
	public static int HaveInPlaceOps = (1 << 3);
	public static int CheckTypes = (1 << 4);
	public static int HaveRichCompare = (1 << 5);
	public static int HaveWeakRefs = (1 << 6);
	public static int HaveIter = (1 << 7);
	public static int HaveClass = (1 << 8);
	public static int HeapType = (1 << 9);
	public static int BaseType = (1 << 10);
	public static int Ready = (1 << 12);
	public static int Readying = (1 << 13);
	public static int HaveGC = (1 << 14);
	public static int Managed = (1 << 29);
	public static int Subclass = (1 << 30);
	public static int Default = (1 << 0) |
	                     (1 << 1) |
	                     (1 << 3) |
	                     (1 << 5) | 
	                     (1 << 6) | 
	                     (1 << 7) |
	                     (1 << 8) | 0;
    }


    // This class defines the function prototypes (delegates) used for low
    // level integration with the CPython runtime. It also provides name 
    // based lookup of the correct prototype for a particular Python type 
    // slot and utilities for generating method thunks.

    internal class Interop {

	static ArrayList keepAlive;
	static Hashtable pmap;
 	static IntPtr temp;

	static Interop() {

	    // Here we build a mapping of PyTypeObject slot names to the
	    // appropriate prototype (delegate) type to use for the slot.

	    Type[] items = typeof(Interop).GetNestedTypes();
	    Hashtable p = new Hashtable();

	    for (int i = 0; i < items.Length; i++) {
		Type item = items[i];
		p[item.Name] = item;
	    }

	    keepAlive = new ArrayList();
	    temp = Marshal.AllocHGlobal(IntPtr.Size);
	    pmap = new Hashtable();

	    pmap["tp_dealloc"] = p["DestructorFunc"];
	    pmap["tp_print"] = p["PrintFunc"];
	    pmap["tp_getattr"] = p["BinaryFunc"];
	    pmap["tp_setattr"] = p["ObjObjArgFunc"];
	    pmap["tp_compare"] = p["ObjObjFunc"];
	    pmap["tp_repr"] = p["UnaryFunc"];
	    pmap["tp_hash"] = p["UnaryFunc"];
	    pmap["tp_call"] = p["TernaryFunc"];
	    pmap["tp_str"] = p["UnaryFunc"];
	    pmap["tp_getattro"] = p["BinaryFunc"];
	    pmap["tp_setattro"] = p["ObjObjArgFunc"];
	    pmap["tp_traverse"] = p["ObjObjArgFunc"];
	    pmap["tp_clear"] = p["InquiryFunc"];
	    pmap["tp_richcompare"] = p["RichCmpFunc"];
	    pmap["tp_iter"] = p["UnaryFunc"];
	    pmap["tp_iternext"] = p["UnaryFunc"];
	    pmap["tp_descr_get"] = p["TernaryFunc"];
	    pmap["tp_descr_set"] = p["ObjObjArgFunc"];
	    pmap["tp_init"] = p["ObjObjArgFunc"];
	    pmap["tp_alloc"] = p["IntArgFunc"];
	    pmap["tp_new"] = p["TernaryFunc"];
	    pmap["tp_free"] = p["DestructorFunc"];
	    pmap["tp_is_gc"] = p["InquiryFunc"];

	    pmap["nb_add"] = p["BinaryFunc"];
	    pmap["nb_subtract"] = p["BinaryFunc"];
	    pmap["nb_multiply"] = p["BinaryFunc"];
	    pmap["nb_divide"] = p["BinaryFunc"];
	    pmap["nb_remainder"] = p["BinaryFunc"];
	    pmap["nb_divmod"] = p["BinaryFunc"];
	    pmap["nb_power"] = p["TernaryFunc"];
	    pmap["nb_negative"] = p["UnaryFunc"];
	    pmap["nb_positive"] = p["UnaryFunc"];
	    pmap["nb_absolute"] = p["UnaryFunc"];
	    pmap["nb_nonzero"] = p["InquiryFunc"];
	    pmap["nb_invert"] = p["UnaryFunc"];
	    pmap["nb_lshift"] = p["BinaryFunc"];
	    pmap["nb_rshift"] = p["BinaryFunc"];
	    pmap["nb_and"] = p["BinaryFunc"];
	    pmap["nb_xor"] = p["BinaryFunc"];
	    pmap["nb_or"] = p["BinaryFunc"];
	    pmap["nb_coerce"] = p["ObjObjFunc"];
	    pmap["nb_int"] = p["UnaryFunc"];
	    pmap["nb_long"] = p["UnaryFunc"];
	    pmap["nb_float"] = p["UnaryFunc"];
	    pmap["nb_oct"] = p["UnaryFunc"];
	    pmap["nb_hex"] = p["UnaryFunc"];
	    pmap["nb_inplace_add"] = p["BinaryFunc"];
	    pmap["nb_inplace_subtract"] = p["BinaryFunc"];
	    pmap["nb_inplace_multiply"] = p["BinaryFunc"];
	    pmap["nb_inplace_divide"] = p["BinaryFunc"];
	    pmap["nb_inplace_remainder"] = p["BinaryFunc"];
	    pmap["nb_inplace_power"] = p["TernaryFunc"];
	    pmap["nb_inplace_lshift"] = p["BinaryFunc"];
	    pmap["nb_inplace_rshift"] = p["BinaryFunc"];
	    pmap["nb_inplace_and"] = p["BinaryFunc"];
	    pmap["nb_inplace_xor"] = p["BinaryFunc"];
	    pmap["nb_inplace_or"] = p["BinaryFunc"];
	    pmap["nb_floor_divide"] = p["BinaryFunc"];
	    pmap["nb_true_divide"] = p["BinaryFunc"];
	    pmap["nb_inplace_floor_divide"] = p["BinaryFunc"];
	    pmap["nb_inplace_true_divide"] = p["BinaryFunc"];

	    pmap["sq_length"] = p["InquiryFunc"];
	    pmap["sq_concat"] = p["BinaryFunc"];
	    pmap["sq_repeat"] = p["IntArgFunc"];
	    pmap["sq_item"] = p["IntArgFunc"];
	    pmap["sq_slice"] = p["IntIntArgFunc"];
	    pmap["sq_ass_item"] = p["IntObjArgFunc"];
	    pmap["sq_ass_slice"] = p["IntIntObjArgFunc"];
	    pmap["sq_contains"] = p["ObjObjFunc"];
	    pmap["sq_inplace_concat"] = p["BinaryFunc"];
	    pmap["sq_inplace_repeat"] = p["IntArgFunc"];

	    pmap["mp_length"] = p["InquiryFunc"];
	    pmap["mp_subscript"] = p["BinaryFunc"];
	    pmap["mp_ass_subscript"] = p["ObjObjArgFunc"];
	    
	    pmap["bf_getreadbuffer"] = p["IntObjArgFunc"];
	    pmap["bf_getwritebuffer"] = p["IntObjArgFunc"];
	    pmap["bf_getsegcount"] = p["ObjObjFunc"];
	    pmap["bf_getcharbuffer"] = p["IntObjArgFunc"];
	}

	internal static Type GetPrototype(string name) {
	    return pmap[name] as Type;
	}

	internal static IntPtr GetThunk(MethodInfo method) {
	    // WARNING: this probably needs a thread lock!
	    Type dt = Interop.GetPrototype(method.Name);
	    if (dt != null) {
		Delegate d = Delegate.CreateDelegate(dt, method);
		MethodThunk cb = new MethodThunk(d);
		Marshal.StructureToPtr(cb, temp, false);
		IntPtr fp = Marshal.ReadIntPtr(temp);
		keepAlive.Add(d);
		return fp;
	    }
	    return IntPtr.Zero;
	}

	[CallConvCdecl()]
	public delegate IntPtr UnaryFunc(IntPtr ob);

	[CallConvCdecl()]
	public delegate IntPtr BinaryFunc(IntPtr ob, IntPtr arg);

	[CallConvCdecl()]
	public delegate IntPtr TernaryFunc(IntPtr ob, IntPtr a1, IntPtr a2);

	[CallConvCdecl()]
	public delegate int InquiryFunc(IntPtr ob);

	[CallConvCdecl()]
	public delegate IntPtr IntArgFunc(IntPtr ob, int arg);

	[CallConvCdecl()]
	public delegate IntPtr IntIntArgFunc(IntPtr ob, int a1, int a2);

	[CallConvCdecl()]
	public delegate int IntObjArgFunc(IntPtr ob, int a1, IntPtr a2);

	[CallConvCdecl()]
	public delegate int IntIntObjArgFunc(IntPtr o, int a, int b, IntPtr c);

	[CallConvCdecl()]
	public delegate int ObjObjArgFunc(IntPtr o, IntPtr a, IntPtr b);

	[CallConvCdecl()]
	public delegate int ObjObjFunc(IntPtr ob, IntPtr arg);

	[CallConvCdecl()]
	public delegate void DestructorFunc(IntPtr ob);

	[CallConvCdecl()]
	public delegate int PrintFunc(IntPtr ob, IntPtr a, int b);

	[CallConvCdecl()]
	public delegate IntPtr RichCmpFunc(IntPtr ob, IntPtr a, int b);

    }


    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
    internal struct MethodThunk {
	public Delegate fn;

	public MethodThunk(Delegate d) {
	    fn = d;
	}
    }

}


=== PythonNet/src/runtime/ClassBase.cs 1.3 => 1.4 ===
--- PythonNet/src/runtime/ClassBase.cs:1.3	Wed Jul 30 10:04:33 2003
+++ PythonNet/src/runtime/ClassBase.cs	Fri Aug  8 15:49:21 2003
@@ -93,6 +93,7 @@
 	}
 
 
+
     }	
 
 }


=== PythonNet/src/runtime/ClassObject.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/ClassObject.cs:1.4	Sat Aug  2 17:55:30 2003
+++ PythonNet/src/runtime/ClassObject.cs	Fri Aug  8 15:49:21 2003
@@ -11,6 +11,7 @@
 
 using System;
 using System.Reflection;
+using System.Runtime.InteropServices;
 
 namespace Python.Runtime {
 
@@ -34,13 +35,68 @@
 	    }
 	}
 
+
 	//====================================================================
 	// Implements __new__ for reflected classes and value types.
 	//====================================================================
 
 	[CallConvCdecl()]
 	public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
-	    ClassObject self = (ClassObject)GetManagedObject(tp);
+
+	    // If this class is a managed subclass (generated by the managed
+	    // metatype), then we just want to call up the __bases__ to get
+	    // the right object created, then fix it up.
+
+	    int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
+
+	    if ((flags & TypeFlags.Subclass) != 0) {
+		// ob = tp.__bases__[0].__new__
+		IntPtr _base = Marshal.ReadIntPtr(tp, TypeOffset.tp_base);
+		if (_base == IntPtr.Zero) {
+		    return Exceptions.InvalidTypeError(tp);
+		}
+		IntPtr func = Marshal.ReadIntPtr(tp, TypeOffset.tp_new);
+		if (func == IntPtr.Zero) {
+		    return Exceptions.InvalidTypeError(tp);
+		}
+
+		IntPtr obj = NativeCall.Call_3(func, _base, args, kw);
+		if (obj == IntPtr.Zero) {
+		    return IntPtr.Zero;
+		}
+
+		// Set ob_type to the managed subclass rather than the type
+		// that created it, and create the __dict__ of the object if
+		// it hasn't been created already. We can get away with this
+		// because we only allow single inheritance and can depend on
+		// a known in-memory format for the instance object.
+
+		Runtime.Decref(_base);
+		Runtime.Incref(tp);
+		Marshal.WriteIntPtr(obj, ObjectOffset.ob_type, tp);
+
+		IntPtr dict = Marshal.ReadIntPtr(obj, ObjectOffset.ob_dict);
+		if (dict == IntPtr.Zero) {
+		    dict = Runtime.PyDict_New();
+		    Marshal.WriteIntPtr(obj, ObjectOffset.ob_dict, dict);
+		}
+
+		return obj;
+	    }
+
+	    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) {
+		Exceptions.SetError(Exceptions.TypeError, 
+				    "invalid managed subclass"
+				    );
+		return IntPtr.Zero;
+	    }
+	    
 	    Type type = self.type;
 
 	    // Primitive types do not have constructors, but they look like
@@ -87,10 +143,10 @@
 	// Implements __init__ for reflected classes and value types.
 	//====================================================================
 
-	[CallConvCdecl()]
-	public static int tp_init(IntPtr ob, IntPtr args, IntPtr kw) {
-	    return 0;
-	}
+//  	[CallConvCdecl()]
+//  	public static int tp_init(IntPtr ob, IntPtr args, IntPtr kw) {
+//  	    return 0;
+//  	}
 
 
 	//====================================================================


=== PythonNet/src/runtime/Exceptions.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/Exceptions.cs:1.4	Fri Aug  1 19:56:10 2003
+++ PythonNet/src/runtime/Exceptions.cs	Fri Aug  8 15:49:21 2003
@@ -178,18 +178,15 @@
 	    Runtime.PyErr_Clear();
 	}
 
-	/// <summary>
-	/// Restore Method
-	/// </summary>
-	///
-	/// <remarks>
-	/// Set Python exception information from the given Python objects.
-	/// This is a wrapper for the Python PyErr_Restore call.
-	/// </remarks>
 
-	//public static void Restore(PyObject type, PyObject val, PyObject tb) {
-	//Runtime.PyErr_Restore(type.Handle, val.Handle, tb.Handle);
-	//}
+
+
+	internal static IntPtr InvalidTypeError(IntPtr tp) {
+	    Exceptions.SetError(Exceptions.TypeError, 
+				"invalid managed type"
+				);
+	    return IntPtr.Zero;
+	}
 
 
 	public static IntPtr ArithmeticError;


=== PythonNet/src/runtime/ManagedType.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/ManagedType.cs:1.1	Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/ManagedType.cs	Fri Aug  8 15:49:21 2003
@@ -70,7 +70,7 @@
 	    for (int i = 0; i < num; i++) {
 		IntPtr item = Marshal.ReadIntPtr(mro, ((3 + i) * IntPtr.Size));
 		int flags = (int)Marshal.ReadIntPtr(item, (21 * IntPtr.Size));
-		if ((flags & (1 << 30)) != 0) {
+		if ((flags & TypeFlags.Managed) != 0) {
 		    IntPtr handle = (tp == ob) ?
 			Marshal.ReadIntPtr(item, (2 * IntPtr.Size)) :
 			Marshal.ReadIntPtr(ob, (2 * IntPtr.Size));


=== PythonNet/src/runtime/MetaType.cs 1.4 => 1.5 ===
--- PythonNet/src/runtime/MetaType.cs:1.4	Sat Aug  2 17:55:30 2003
+++ PythonNet/src/runtime/MetaType.cs	Fri Aug  8 15:49:21 2003
@@ -26,6 +26,7 @@
 
 	// static Type delegateType;
 	static IntPtr PyCLRMetaType;
+	static IntPtr py__init__;
 	static IntPtr stdflags;
 	static ArrayList dList;
 	static Hashtable cache;
@@ -37,9 +38,10 @@
 	    tpSize = Marshal.SizeOf(new PyTypeObject());
 	    cache = new Hashtable();
 	    dList = new ArrayList();
-	    stdflags = (IntPtr) (PyTypeFlags.Default | 
-				 PyTypeFlags.HeapType |
-				 PyTypeFlags.Managed);
+	    stdflags = (IntPtr) (TypeFlags.Default | 
+				 TypeFlags.HeapType |
+				 TypeFlags.Subclass |
+				 TypeFlags.Managed);
 	}
 
 	//====================================================================
@@ -47,11 +49,12 @@
 	//====================================================================
 
 	public static IntPtr Initialize() {
+	    py__init__ = Runtime.PyString_FromString("__init__");
 
-	    Type implType = typeof(MetaType);
+	    Type type = typeof(MetaType);
 
 	    PyTypeObject pyTypeObj = new PyTypeObject();
-	    pyTypeObj.tp_name = Marshal.StringToHGlobalAnsi(implType.Name);
+	    pyTypeObj.tp_name = Marshal.StringToHGlobalAnsi(type.Name);
 
 	    pyTypeObj.ob_type = Runtime.PyTypeType;
 	    Runtime.Incref(Runtime.PyTypeType);
@@ -59,47 +62,33 @@
 	    pyTypeObj.tp_base = Runtime.PyTypeType;
 	    Runtime.Incref(Runtime.PyTypeType);
 
-	    int typeSize = Marshal.SizeOf(typeof(PyTypeObject));
-	    pyTypeObj.tp_basicsize = (IntPtr)typeSize;
+	    pyTypeObj.tp_basicsize = (IntPtr)tpSize;
 	    pyTypeObj.ob_refcnt = (IntPtr) 1;
-	    pyTypeObj.tp_flags = (IntPtr) (PyTypeFlags.Default | 
-					   PyTypeFlags.HeapType |
-					   PyTypeFlags.Managed);
+	    pyTypeObj.tp_flags = (IntPtr) (TypeFlags.Default | 
+					   TypeFlags.HeapType |
+					   TypeFlags.Managed);
 
-	    IntPtr pThunk = Marshal.AllocHGlobal(IntPtr.Size);
 	    BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
-	    Type th = typeof(CallbackThunks);
 	    Type py = pyTypeObj.GetType();
-	    Type tp = implType;
 
-	    while (tp != null) {
-		foreach (MethodInfo method in tp.GetMethods(flags)) {
-		    string methodName = method.Name;
-		    if (! methodName.StartsWith("tp_") ) {
+	    while (type != null) {
+		MethodInfo[] methods = type.GetMethods(flags);
+		for (int i = 0; i < methods.Length; i++) {
+		    MethodInfo method = methods[i];
+		    string name = method.Name;
+		    if (! name.StartsWith("tp_") ) {
 			continue;
 		    }
 
-		    FieldInfo slot = py.GetField(methodName);
-		    if (slot != null && 
-			(IntPtr)slot.GetValue(pyTypeObj) == IntPtr.Zero) {
-
-			Type dt = th.GetNestedType(methodName);
-			if (dt != null) {
-			    Delegate d = Delegate.CreateDelegate(dt, method);
-			    CallbackThunk cb = new CallbackThunk(d);
-
-			    Marshal.StructureToPtr(cb, pThunk, false);
-			    IntPtr fp = Marshal.ReadIntPtr(pThunk);
-			    slot.SetValue(pyTypeObj, fp);
-			    dList.Add(d);
-			}
+		    FieldInfo fi = py.GetField(name);
+		    IntPtr value = (IntPtr) fi.GetValue(pyTypeObj);
+		    if ((fi != null) && (value == IntPtr.Zero)) {
+			fi.SetValue(pyTypeObj, Interop.GetThunk(method));
 		    }
 		}
-		tp = tp.BaseType;
+		type = type.BaseType;
 	    }
 
-	    Marshal.FreeHGlobal(pThunk);
-
 	    // Now blit the PyTypeObject instance to the unmanaged heap. This
 	    // bit lets us avoid pinning objects, which would disrupt the GC.
 
@@ -109,42 +98,12 @@
 	    gch.Free();
 	    Runtime.PyType_Ready(typePtr);
 
-
 	    PyCLRMetaType = typePtr;
 	    return typePtr;
 	}
 
 
 
-	//====================================================================
-	// Type __setattr__ implementation for reflected types. Note that this
-	// is slightly different than the standard setattr implementation for
-	// the normal Python metatype (PyTypeType). We need to look first in
-	// the type object of a reflected type for a descriptor in order to 
-	// support the right setattr behavior for static fields and properties.
-	//====================================================================
-
-	[CallConvCdecl()]
-	public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value) {
-	    IntPtr descr = Runtime._PyType_Lookup(tp, name);
-
-	    if (descr != IntPtr.Zero) {
-		IntPtr dt = Runtime.PyObject_TYPE(descr);
-		IntPtr fp = Marshal.ReadIntPtr(dt, (35 * IntPtr.Size));
-		if (fp != IntPtr.Zero) {
-		    return NativeCall.Impl.Int_Call_3(fp, descr, name, value);
-		}
-		Exceptions.SetError(Exceptions.AttributeError,
-				    "attribute is read-only");
-		return -1;
-	    }
-	    
-	    if (Runtime.PyObject_GenericSetAttr(tp, name, value) < 0) {
-		return -1;
-	    }
-
-	    return 0;
-	}
 
 
 	//====================================================================
@@ -229,6 +188,7 @@
 	    sub.ob_refcnt = (IntPtr) 1;
 	    sub.tp_flags = stdflags;
 	    sub.tp_basicsize = (IntPtr)tpSize;
+	    sub.tp_dictoffset = (IntPtr) ObjectOffset.ob_dict;
 
 	    sub.tp_base = basetype;
 	    Runtime.Incref(basetype);
@@ -238,9 +198,13 @@
 
 	    sub.tp_dict = dict;
 
-	    // get/set attr copy?
+	    // get/set attr copy
+	    //IntPtr mt = Runtime.PyTypeType;
+	    //IntPtr fp = Marshal.ReadIntPtr(mt, TypeOffset.tp_getattro);
+	    //sub.tp_getattro = fp;
 
-	    // copy hidden obj
+
+	    // copy hidden obj !!!!do we need to copy gchandle??
   	    sub.ob_size = Marshal.ReadIntPtr(basetype, 2 * IntPtr.Size);
 
 	    IntPtr op = Runtime.PyMem_Malloc(tpSize);
@@ -260,6 +224,79 @@
 
 
 	//====================================================================
+	// Metatype __call__ implementation. This is needed to ensure correct
+	// initialization (__init__ support), because the tp_call we inherit
+	// from PyType_Type won't do initialization for types that do not use
+	// the standard metatype.
+	//====================================================================
+
+	[CallConvCdecl()]
+	public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw) {
+	    IntPtr func = Marshal.ReadIntPtr(tp, TypeOffset.tp_new);
+	    if (func == IntPtr.Zero) {
+		return Exceptions.InvalidTypeError(tp);
+	    }
+	    
+	    IntPtr obj = NativeCall.Call_3(func, tp, args, kw);
+	    if (obj == IntPtr.Zero) {
+		return IntPtr.Zero;
+	    }
+
+	    IntPtr type = Runtime.PyObject_TYPE(obj);
+	    IntPtr init = Runtime._PyType_Lookup(type, py__init__);
+	    Runtime.PyErr_Clear();
+
+	    if (init != IntPtr.Zero) {
+		IntPtr bound = Runtime.GetBoundArgTuple(obj, args);
+		if (bound == IntPtr.Zero) {
+		    Runtime.Decref(obj);
+		    return IntPtr.Zero;
+		}
+
+		IntPtr result = Runtime.PyObject_Call(init, bound, kw);
+		if (result == IntPtr.Zero) {
+		    Runtime.Decref(obj);
+		    return IntPtr.Zero;
+		}
+		Runtime.Decref(result);
+	    }
+
+	    return obj;
+	}
+
+
+	//====================================================================
+	// Type __setattr__ implementation for reflected types. Note that this
+	// is slightly different than the standard setattr implementation for
+	// the normal Python metatype (PyTypeType). We need to look first in
+	// the type object of a reflected type for a descriptor in order to 
+	// support the right setattr behavior for static fields and properties.
+	//====================================================================
+
+	[CallConvCdecl()]
+	public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value) {
+	    IntPtr descr = Runtime._PyType_Lookup(tp, name);
+
+	    if (descr != IntPtr.Zero) {
+		IntPtr dt = Runtime.PyObject_TYPE(descr);
+		IntPtr fp = Marshal.ReadIntPtr(dt, (35 * IntPtr.Size));
+		if (fp != IntPtr.Zero) {
+		    return NativeCall.Impl.Int_Call_3(fp, descr, name, value);
+		}
+		Exceptions.SetError(Exceptions.AttributeError,
+				    "attribute is read-only");
+		return -1;
+	    }
+	    
+	    if (Runtime.PyObject_GenericSetAttr(tp, name, value) < 0) {
+		return -1;
+	    }
+
+	    return 0;
+	}
+
+
+	//====================================================================
 	// Dealloc implementation. This is called when a subclass generated
 	// by this metatype is no longer referenced in Python.
 	//====================================================================
@@ -274,13 +311,6 @@
 	    Runtime.PyMem_Free(tp);
 	}
 
-	/*
-	[CallConvCdecl()]
-	public static IntPtr tp_repr(IntPtr ob) {
-	    ClassBase self = (ClassBase)GetManagedObject(ob);
-	    return self.ClassRepr();
-	}
-	*/
 
     }
 


=== PythonNet/src/runtime/MethodWrapper.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/MethodWrapper.cs:1.1	Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/MethodWrapper.cs	Fri Aug  8 15:49:21 2003
@@ -42,11 +42,10 @@
 	    // Currently, these are never released. need to think harder.
 
 	    mDelegate = Delegate.CreateDelegate(
-				 typeof(Prototypes.TernaryFunc), 
-				 //CallbackThunks.generic),
+				 typeof(Interop.TernaryFunc), 
 				 obType.GetMethod(name)
 				 );
-	    CallbackThunk cb = new CallbackThunk(mDelegate);
+	    MethodThunk cb = new MethodThunk(mDelegate);
 	    IntPtr pThunk = Marshal.AllocHGlobal(IntPtr.Size);
 	    Marshal.StructureToPtr(cb, pThunk, false);
 	    IntPtr fp = Marshal.ReadIntPtr(pThunk);


=== PythonNet/src/runtime/NativeCall.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/NativeCall.cs:1.1	Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/NativeCall.cs	Fri Aug  8 15:49:21 2003
@@ -136,6 +136,16 @@
 	    Impl.Void_Call_1(fp, a1);
 	}
 
+	public static IntPtr Call_3(IntPtr fp, IntPtr a1, IntPtr a2, 
+				    IntPtr a3) {
+	    return Impl.Call_3(fp, a1, a2, a3);
+	}
+
+	public static int Int_Call_3(IntPtr fp, IntPtr a1, IntPtr a2, 
+				     IntPtr a3) {
+	    return Impl.Int_Call_3(fp, a1, a2, a3);
+	}
+
     }
 
 


=== PythonNet/src/runtime/Runtime.cs 1.5 => 1.6 ===
--- PythonNet/src/runtime/Runtime.cs:1.5	Sat Aug  2 17:55:30 2003
+++ PythonNet/src/runtime/Runtime.cs	Fri Aug  8 15:49:21 2003
@@ -139,6 +139,25 @@
 
 
 
+	internal static IntPtr GetBoundArgTuple(IntPtr obj, IntPtr args) {
+	    if (Runtime.PyObject_TYPE(args) != Runtime.PyTupleType) {
+		Exceptions.SetError(Exceptions.TypeError, "tuple expected");
+		return IntPtr.Zero;
+	    }
+	    int size = Runtime.PyTuple_Size(args);
+	    IntPtr items = Runtime.PyTuple_New(size + 1);
+	    Runtime.PyTuple_SetItem(items, 0, obj);
+	    Runtime.Incref(obj);
+
+	    for (int i = 0; i < size; i++) {
+		IntPtr item = Runtime.PyTuple_GetItem(args, i);
+		Runtime.Incref(item);
+		Runtime.PyTuple_SetItem(items, i + 1, item);   
+	    }
+
+	    return items;
+	}
+
 
 	//===================================================================
 	// Managed exports of the Python C API. Where appropriate, we do 


=== PythonNet/src/runtime/TypeManager.cs 1.5 => 1.6 ===
--- PythonNet/src/runtime/TypeManager.cs:1.5	Sat Aug  2 17:55:30 2003
+++ PythonNet/src/runtime/TypeManager.cs	Fri Aug  8 15:49:21 2003
@@ -95,7 +95,7 @@
 		    FieldInfo fi = typedesc.GetField(name);
 		    IntPtr value = (IntPtr) fi.GetValue(typeObj);
 		    if ((fi != null) && (value == IntPtr.Zero)) {
-			fi.SetValue(typeObj, Prototypes.GetThunk(method));
+			fi.SetValue(typeObj, Interop.GetThunk(method));
 		    }
 		}
 		type = type.BaseType;
@@ -177,8 +177,8 @@
 
 	    pyTypeObj.tp_basicsize = (IntPtr)(3 * IntPtr.Size);
 	    pyTypeObj.ob_refcnt = (IntPtr) 1;  // ??
-	    pyTypeObj.tp_flags = (IntPtr) (PyTypeFlags.Default | 
-					   PyTypeFlags.Managed);
+	    pyTypeObj.tp_flags = (IntPtr) (TypeFlags.Default | 
+					   TypeFlags.Managed);
 
 	    InitializeSlots(pyTypeObj, obType);
 
@@ -217,10 +217,10 @@
 	    pyTypeObj.ob_size = (IntPtr)obj.gcHandle;
 	    pyTypeObj.tp_basicsize = (IntPtr)(3 * IntPtr.Size);
 	    pyTypeObj.ob_refcnt = (IntPtr) 1;  // ??
-	    pyTypeObj.tp_flags = (IntPtr) (PyTypeFlags.Default | 
-					   PyTypeFlags.BaseType |
-					   PyTypeFlags.HeapType |
-					   PyTypeFlags.Managed);
+	    pyTypeObj.tp_flags = (IntPtr) (TypeFlags.Default | 
+					   TypeFlags.BaseType |
+					   TypeFlags.HeapType |
+					   TypeFlags.Managed);
 	    //pyTypeObj.tp_dictoffset = (IntPtr) (3 * IntPtr.Size);
 
 	    InitializeSlots(pyTypeObj, obj.GetType());

=== Removed File PythonNet/src/runtime/CallbackThunks.cs ===




More information about the Zope-CVS mailing list