[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