[Zope-CVS] CVS: PythonNet/src/runtime - Python.cs:1.1 ArrayObject.cs:1.2 CallbackThunks.cs:1.2 ClassManager.cs:1.3 ClassObject.cs:1.2 ConstructorBinder.cs:1.2 Converter.cs:1.2 DebugHelper.cs:1.2 DelegateManager.cs:1.2 DelegateObject.cs:1.2 Exceptions.cs:1.2 Indexer.cs:1.2 MethodBinder.cs:1.2 PropertyObject.cs:1.2 PythonException.cs:1.2 Runtime.cs:1.2 TypeManager.cs:1.3 PythonInterpreter.cs:NONE
Brian Lloyd
brian@zope.com
Mon, 28 Jul 2003 22:28:58 -0400
Update of /cvs-repository/PythonNet/src/runtime
In directory cvs.zope.org:/tmp/cvs-serv5111/src/runtime
Modified Files:
ArrayObject.cs CallbackThunks.cs ClassManager.cs
ClassObject.cs ConstructorBinder.cs Converter.cs
DebugHelper.cs DelegateManager.cs DelegateObject.cs
Exceptions.cs Indexer.cs MethodBinder.cs PropertyObject.cs
PythonException.cs Runtime.cs TypeManager.cs
Added Files:
Python.cs
Removed Files:
PythonInterpreter.cs
Log Message:
added indexer support, array support and preliminary thread primitives
=== Added File PythonNet/src/runtime/Python.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.Threading;
using System.Collections;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// This class represents the public interface of the Python runtime.
///
/// </summary>
public class PythonEngine {
private static Hashtable threads;
private static bool initialized;
private static IntPtr istate;
//====================================================================
// Initialize the Python runtime. It is safe to call this method more
// than once, though initialization will only happen on the first call.
//====================================================================
public static void Initialize() {
if (!initialized) {
Runtime.Initialize();
threads = new Hashtable();
IntPtr ts = Runtime.PyThreadState_Get();
threads[Thread.CurrentThread] = ts;
// bleah - fix this!
istate = Marshal.ReadIntPtr(ts, 1 * IntPtr.Size);
initialized = true;
}
}
//====================================================================
// Shutdown and clean up the Python runtime. After calling this method,
// the Python runtime can no longer be used in the current process.
//====================================================================
public static void Finalize() {
if (initialized) {
Runtime.Py_Finalize();
initialized = false;
}
}
/*
// Note that the semantics of these thread management APIs are fairly
// different from those of the C Python APIs. The managed integration
// layer has to support nearly arbitrarily reentrant code since Python
// can call managed code which calls back into Python, etc.
*/
//====================================================================
// Ensure that the currently executing thread is known to the Python
// interpreter. This is mainly called by async support code that may
// be called on system thread pool threads.
//====================================================================
public static IntPtr EnsureThread() {
Thread t = Thread.CurrentThread;
Object v = threads[t];
if (v == null) {
IntPtr ts = Runtime.PyThreadState_New(istate);
threads[t] = ts;
return ts;
}
return (IntPtr) v;
}
//====================================================================
// Acquire the Python interpreter lock unconditionally. It is safe to
// call this even if the calling thread already owns the interpreter
// lock (in which case it doesn't change the lock state).
//====================================================================
public static void AcquireThreadLock() {
IntPtr current = Runtime.PyThreadState_Swap(IntPtr.Zero);
Runtime.PyThreadState_Swap(current);
IntPtr ts = EnsureThread(); // should inline
if (ts != current) {
Runtime.PyEval_RestoreThread(ts);
}
}
//====================================================================
// Release the Python interpreter lock unconditionally. It is safe to
// call this even if the calling thread does not own the interpreter
// lock (in which case it doesn't change the lock state).
//====================================================================
public static void ReleaseThreadLock() {
IntPtr current = Runtime.PyThreadState_Swap(IntPtr.Zero);
Runtime.PyThreadState_Swap(current);
IntPtr ts = EnsureThread();
if (ts == current) {
ts = Runtime.PyEval_SaveThread();
}
}
//====================================================================
// Interpreter properties
//====================================================================
public static bool IsInitialized {
get {
return initialized;
}
}
public static string ProgramName {
get {
string result = Runtime.Py_GetProgramName();
if (result == null) {
return "";
}
return result;
}
set {
Runtime.Py_SetProgramName(value);
}
}
public static string PythonHome {
get {
string result = Runtime.Py_GetPythonHome();
if (result == null) {
return "";
}
return result;
}
set {
Runtime.Py_SetPythonHome(value);
}
}
public static string Version {
get {
return Runtime.Py_GetVersion();
}
}
public static string BuildInfo {
get {
return Runtime.Py_GetBuildInfo();
}
}
public static string Platform {
get {
return Runtime.Py_GetPlatform();
}
}
public static string Copyright {
get {
return Runtime.Py_GetCopyright();
}
}
public static int RunSimpleString(string code) {
return Runtime.PyRun_SimpleString(code);
}
// public static PyModule ImportModule(string name) {
// PyString moduleName = new PyString(name);
// IntPtr pointer = Runtime.PyImport_Import(moduleName.Handle);
// return new PyModule(pointer);
// }
// public static PyModule ReloadModule(PyModule module) {
// IntPtr pointer = Runtime.PyImport_ReloadModule(module.Handle);
// return new PyModule(pointer);
// }
// public static PyModule AddModule(string name) {
// IntPtr result = Runtime.PyImport_AddModule(name);
// if (result == IntPtr.Zero) {
// throw new PythonException();
// }
// Runtime.Incref(result);
// return new PyModule(result);
// }
}
}
=== PythonNet/src/runtime/ArrayObject.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/ArrayObject.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/ArrayObject.cs Mon Jul 28 22:28:15 2003
@@ -39,21 +39,236 @@
}
[CallConvCdecl()]
- public static IntPtr tp_init(IntPtr ob, IntPtr args, IntPtr kw) {
+ public static int tp_init(IntPtr ob, IntPtr args, IntPtr kw) {
Exceptions.SetError(Exceptions.TypeError,
"cannot instantiate array wrapper"
);
- return IntPtr.Zero;
+ return -1;
}
- /*
+
+ //====================================================================
+ // Implements __getitem__ for array types.
+ //====================================================================
+
+ [CallConvCdecl()]
+ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) {
+ CLRObject obj = (CLRObject)ManagedType.GetManagedObject(ob);
+ Array items = obj.inst as Array;
+ Type itemType = obj.inst.GetType().GetElementType();
+ int rank = items.Rank;
+ int index = 0;
+ object value;
+
+ // Note that CLR 1.0 only supports int indexes - methods to
+ // support long indices were introduced in 1.1. We could
+ // support long indices automatically, but given that long
+ // indices are not backward compatible and a relative edge
+ // case, we won't bother for now.
+
+ // Single-dimensional arrays are the most common case and are
+ // cheaper to deal with than multi-dimensional, so check first.
+
+ if (rank == 1) {
+ index = (int)Runtime.PyInt_AsLong(idx);
+
+ if (Exceptions.ErrorOccurred()) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "invalid index value"
+ );
+ return IntPtr.Zero;
+ }
+
+ if (index < 0) {
+ index = items.Length + index;
+ }
+
+ try {
+ value = items.GetValue(index);
+ }
+ catch (IndexOutOfRangeException) {
+ Exceptions.SetError(Exceptions.IndexError,
+ "array index out of range"
+ );
+ return IntPtr.Zero;
+ }
+
+ return Converter.ToPython(items.GetValue(index), itemType);
+ }
+
+ // Multi-dimensional arrays can be indexed a la: list[1, 2, 3].
+
+ if (!Runtime.PyTuple_Check(idx)) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "invalid index value"
+ );
+ return IntPtr.Zero;
+ }
+
+ int count = Runtime.PyTuple_Size(idx);
+
+ Array args = Array.CreateInstance(typeof(Int32), count);
+
+ for (int i = 0; i < count; i++) {
+ IntPtr op = Runtime.PyTuple_GetItem(idx, i);
+ index = (int)Runtime.PyInt_AsLong(op);
+
+ if (Exceptions.ErrorOccurred()) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "invalid index value"
+ );
+ return IntPtr.Zero;
+ }
+
+ if (index < 0) {
+ index = items.GetLength(i) + index;
+ }
+
+ args.SetValue(index, i);
+ }
+
+ try {
+ value = items.GetValue((int[]) args);
+ }
+ catch (IndexOutOfRangeException) {
+ Exceptions.SetError(Exceptions.IndexError,
+ "array index out of range"
+ );
+ return IntPtr.Zero;
+ }
+
+ return Converter.ToPython(value, itemType);
+ }
+
+
+ //====================================================================
+ // Implements __setitem__ for array types.
+ //====================================================================
+
+ [CallConvCdecl()]
+ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) {
+ CLRObject obj = (CLRObject)ManagedType.GetManagedObject(ob);
+ Array items = obj.inst as Array;
+ Type itemType = obj.inst.GetType().GetElementType();
+ int rank = items.Rank;
+ int index = 0;
+ object value;
+
+ if (items.IsReadOnly) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "array is read-only"
+ );
+ return -1;
+ }
+
+ if (!Converter.ToManaged(v, itemType, out value, true)) {
+ return -1;
+ }
+
+ if (rank == 1) {
+ index = (int)Runtime.PyInt_AsLong(idx);
+
+ if (Exceptions.ErrorOccurred()) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "invalid index value"
+ );
+ return -1;
+ }
+
+ if (index < 0) {
+ index = items.Length + index;
+ }
+
+ try {
+ items.SetValue(value, index);
+ }
+ catch (IndexOutOfRangeException) {
+ Exceptions.SetError(Exceptions.IndexError,
+ "array index out of range"
+ );
+ return -1;
+ }
+
+ return 0;
+ }
+
+ if (!Runtime.PyTuple_Check(idx)) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "invalid index value"
+ );
+ return -1;
+ }
+
+ int count = Runtime.PyTuple_Size(idx);
+
+ Array args = Array.CreateInstance(typeof(Int32), count);
+
+ for (int i = 0; i < count; i++) {
+ IntPtr op = Runtime.PyTuple_GetItem(idx, i);
+ index = (int)Runtime.PyInt_AsLong(op);
+
+ if (Exceptions.ErrorOccurred()) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "invalid index value"
+ );
+ return -1;
+ }
+
+ if (index < 0) {
+ index = items.GetLength(i) + index;
+ }
+
+ args.SetValue(index, i);
+ }
+
+ try {
+ items.SetValue(value, (int[])args);
+ }
+ catch (IndexOutOfRangeException) {
+ Exceptions.SetError(Exceptions.IndexError,
+ "array index out of range"
+ );
+ return -1;
+ }
+
+ return 0;
+ }
+
+
+ //====================================================================
+ // Implements __contains__ for array types.
+ //====================================================================
+
[CallConvCdecl()]
- public static IntPtr tp_repr(IntPtr ob) {
- ArrayObject self = (ArrayObject)GetManagedObject(ob);
- string s = String.Format("<array '{0}'>", self.type.Name);
- return Runtime.PyString_FromStringAndSize(s, s.Length);
+ public static int sq_contains(IntPtr ob, IntPtr v) {
+ CLRObject obj = (CLRObject)ManagedType.GetManagedObject(ob);
+ Type itemType = obj.inst.GetType().GetElementType();
+ IList items = obj.inst as IList;
+ object value;
+
+ if (!Converter.ToManaged(v, itemType, out value, false)) {
+ return 0;
+ }
+
+ if (items.Contains(value)) {
+ return 1;
+ }
+
+ return 0;
}
- */
+
+
+ //====================================================================
+ // Implements __len__ for array types.
+ //====================================================================
+
+ [CallConvCdecl()]
+ public static int mp_length(IntPtr ob) {
+ CLRObject self = (CLRObject)ManagedType.GetManagedObject(ob);
+ Array items = self.inst as Array;
+ return items.Length;
+ }
+
}
=== PythonNet/src/runtime/CallbackThunks.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/CallbackThunks.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/CallbackThunks.cs Mon Jul 28 22:28:15 2003
@@ -318,7 +318,6 @@
internal static IntPtr GetThunk(MethodInfo method) {
// WARNING: this probably needs a thread lock!
- //Type dt = typeof(CallbackThunks).GetNestedType(method.Name);
Type dt = Prototypes.GetPrototype(method.Name);
if (dt != null) {
Delegate d = Delegate.CreateDelegate(dt, method);
=== PythonNet/src/runtime/ClassManager.cs 1.2 => 1.3 ===
--- PythonNet/src/runtime/ClassManager.cs:1.2 Thu Jul 24 19:55:00 2003
+++ PythonNet/src/runtime/ClassManager.cs Mon Jul 28 22:28:15 2003
@@ -100,7 +100,6 @@
impl.tpHandle = TypeManager.GetTypeHandle(impl, type);
-
// Finally, initialize the class __dict__ and return the object.
IntPtr pp = Runtime._PyObject_GetDictPtr(impl.tpHandle);
=== PythonNet/src/runtime/ClassObject.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/ClassObject.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/ClassObject.cs Mon Jul 28 22:28:15 2003
@@ -93,6 +93,100 @@
}
+ //====================================================================
+ // Implements __getitem__ for reflected classes and value types.
+ //====================================================================
+
+ [CallConvCdecl()]
+ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) {
+ ManagedType self = GetManagedObject(ob);
+ IntPtr tp = Runtime.PyObject_Type(ob);
+ ClassBase cls = (ClassBase)GetManagedObject(tp);
+
+ if (cls.indexer == null || !cls.indexer.CanGet) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "unindexable object"
+ );
+ return IntPtr.Zero;
+ }
+
+ // Arg may be a tuple in the case of an indexer with multiple
+ // parameters. If so, use it directly, else make a new tuple
+ // with the index arg (method binders expect arg tuples).
+
+ IntPtr args = idx;
+ bool free = false;
+
+ if (!Runtime.PyTuple_Check(idx)) {
+ args = Runtime.PyTuple_New(1);
+ Runtime.PyTuple_SetItem(args, 0, idx);
+ free = true;
+ }
+
+ IntPtr value = cls.indexer.GetItem(ob, args);
+
+ if (free) {
+ Runtime.Decref(args);
+ }
+
+ return value;
+ }
+
+
+ //====================================================================
+ // Implements __setitem__ for reflected classes and value types.
+ //====================================================================
+
+ [CallConvCdecl()]
+ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) {
+ ManagedType self = GetManagedObject(ob);
+ IntPtr tp = Runtime.PyObject_Type(ob);
+ ClassBase cls = (ClassBase)GetManagedObject(tp);
+
+ if (cls.indexer == null || !cls.indexer.CanSet) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "object doesn't support item assignment x"
+ );
+ return -1;
+ }
+
+ // Arg may be a tuple in the case of an indexer with multiple
+ // parameters. If so, use it directly, else make a new tuple
+ // with the index arg (method binders expect arg tuples).
+
+ IntPtr args = idx;
+ bool free = false;
+
+ if (!Runtime.PyTuple_Check(idx)) {
+ args = Runtime.PyTuple_New(1);
+ Runtime.PyTuple_SetItem(args, 0, idx);
+ free = true;
+ }
+
+ int i = Runtime.PyTuple_Size(args);
+ IntPtr real = Runtime.PyTuple_New(i + 1);
+ for (int n = 0; n < i; n++) {
+ IntPtr item = Runtime.PyTuple_GetItem(args, n);
+ Runtime.PyTuple_SetItem(real, n, item);
+ }
+ Runtime.PyTuple_SetItem(real, i, v);
+
+ IntPtr value = cls.indexer.SetItem(ob, real);
+
+ Runtime.Decref(real);
+
+ if (free) {
+ Runtime.Decref(args);
+ }
+
+ if (Exceptions.ErrorOccurred()) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+
}
}
=== PythonNet/src/runtime/ConstructorBinder.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/ConstructorBinder.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/ConstructorBinder.cs Mon Jul 28 22:28:15 2003
@@ -39,6 +39,8 @@
}
ConstructorInfo ci = (ConstructorInfo)binding.info;
+ // IntPtr ts = PythonEngine.BeginAllowThreads();
+
try {
result = ci.Invoke(binding.args);
}
@@ -46,10 +48,12 @@
if (e.InnerException != null) {
e = e.InnerException;
}
+ //PythonEngine.EndAllowThreads(ts);
Exceptions.SetError(e);
return IntPtr.Zero;
}
+ //PythonEngine.EndAllowThreads(ts);
return Converter.ToPython(result, result.GetType());
}
=== PythonNet/src/runtime/Converter.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/Converter.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/Converter.cs Mon Jul 28 22:28:15 2003
@@ -27,10 +27,16 @@
private Converter() {}
static Type objectType;
+ static Type stringType;
+ static Type int32Type;
+ static Type int64Type;
static Type flagsType;
static Converter () {
objectType = typeof(Object);
+ stringType = typeof(String);
+ int32Type = typeof(Int32);
+ int64Type = typeof(Int64);
flagsType = typeof(FlagsAttribute);
}
@@ -152,11 +158,38 @@
return ToEnum(value, obType, out result, setError);
}
- if (value == Runtime.PyNone && !obType.IsPrimitive) {
+ if (value == Runtime.PyNone && !obType.IsValueType) {
result = null;
return true;
}
+ // Conversion to 'Object' is done based on some reasonable
+ // default conversions (Python string -> managed string,
+ // Python int -> Int32 etc.).
+
+ if (obType == objectType) {
+ if (Runtime.IsStringType(value)) {
+ return ToPrimitive(value, stringType, out result,
+ setError);
+ }
+
+ else if (Runtime.PyInt_Check(value)) {
+ return ToPrimitive(value, int32Type, out result, setError);
+ }
+
+ else if (Runtime.PyLong_Check(value)) {
+ return ToPrimitive(value, int64Type, out result, setError);
+ }
+
+ if (setError) {
+ Exceptions.SetError(Exceptions.TypeError,
+ "value cannot be converted to Object"
+ );
+ }
+
+ return false;
+ }
+
return ToPrimitive(value, obType, out result, setError);
}
@@ -460,6 +493,8 @@
return false;
}
+
+
}
=== PythonNet/src/runtime/DebugHelper.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/DebugHelper.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/DebugHelper.cs Mon Jul 28 22:28:15 2003
@@ -36,7 +36,6 @@
}
-
}
=== PythonNet/src/runtime/DelegateManager.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/DelegateManager.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/DelegateManager.cs Mon Jul 28 22:28:15 2003
@@ -194,7 +194,6 @@
too "special" for this to work. It would be more work, so for now
the 80/20 rule applies :)
- TODO: how does async invokation of a delegate work w/Python?
*/
public class Dispatcher {
@@ -203,18 +202,23 @@
public Type dtype;
public Dispatcher(IntPtr target, Type dtype) {
-
- // method / target object.
Runtime.Incref(target);
this.target = target;
this.dtype = dtype;
}
+ public void Finalize() {
+ Runtime.Decref(target);
+ }
+
public object Dispatch(ArrayList args) {
// check refs
- // TODO: Should probably check here to see if we are being called
- // on an async thread. If so, need to register with Python.
+ // Delegates with Python implementations may be invoked on a
+ // thread from the system thread pool, so we need to ensure
+ // that Python knows about this thread.
+
+ PythonEngine.AcquireThreadLock();
MethodInfo method = dtype.GetMethod("Invoke");
ParameterInfo[] pi = method.GetParameters();
@@ -250,21 +254,6 @@
return result;
}
- public void Finalize() {
- // The dispatcher instance owns the reference to the Python
- // method. When the true delegate dies, we die and can decref.
- Runtime.Decref(target);
- }
-
- /*
- public object InvokeTemplate(int a1, int a2, int a3) {
- ArrayList args = new ArrayList();
- args.Add(a1);
- args.Add(a2);
- args.Add(a3);
- return this.Dispatch(args);
- }
- */
}
=== PythonNet/src/runtime/DelegateObject.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/DelegateObject.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/DelegateObject.cs Mon Jul 28 22:28:15 2003
@@ -27,6 +27,7 @@
internal DelegateObject(Type tp) : base(tp) {
binder = new MethodBinder(tp.GetMethod("Invoke"));
+ binder.FreeThreaded = false;
}
//====================================================================
=== PythonNet/src/runtime/Exceptions.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/Exceptions.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/Exceptions.cs Mon Jul 28 22:28:15 2003
@@ -120,6 +120,25 @@
/// </remarks>
public static void SetError(Exception e) {
+
+ // Because delegates allow arbitrary nestings of Python calling
+ // managed calling Python calling... etc. it is possible that we
+ // might get a managed exception raised that is a wrapper for a
+ // Python exception. In that case we'd rather have the real thing.
+
+ PythonException err = e as PythonException;
+ if (err != null) {
+ if (err.Type == IntPtr.Zero) {
+ Console.WriteLine("null!");
+ }
+ if (err.Value == IntPtr.Zero) {
+ Console.WriteLine("null!");
+ }
+
+ Runtime.PyErr_SetObject(err.Type, err.Value);
+ return;
+ }
+
Runtime.PyErr_Clear();
IntPtr op = CLRObject.GetInstHandle(e);
Runtime.Incref(op);
=== PythonNet/src/runtime/Indexer.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/Indexer.cs:1.1 Thu Jul 24 19:55:00 2003
+++ PythonNet/src/runtime/Indexer.cs Mon Jul 28 22:28:15 2003
@@ -30,6 +30,20 @@
SetterBinder = new MethodBinder();
}
+
+ public bool CanGet {
+ get {
+ return GetterBinder.Count > 0;
+ }
+ }
+
+ public bool CanSet {
+ get {
+ return SetterBinder.Count > 0;
+ }
+ }
+
+
public void AddProperty(PropertyInfo pi) {
MethodInfo getter = pi.GetGetMethod(true);
MethodInfo setter = pi.GetSetMethod(true);
@@ -39,6 +53,15 @@
if (setter != null) {
SetterBinder.AddMethod(setter);
}
+ }
+
+ internal IntPtr GetItem(IntPtr inst, IntPtr args) {
+ return GetterBinder.Invoke(inst, args, IntPtr.Zero);
+ }
+
+
+ internal IntPtr SetItem(IntPtr inst, IntPtr args) {
+ return SetterBinder.Invoke(inst, args, IntPtr.Zero);
}
}
=== PythonNet/src/runtime/MethodBinder.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/MethodBinder.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/MethodBinder.cs Mon Jul 28 22:28:15 2003
@@ -25,7 +25,8 @@
internal class MethodBinder {
// MethodInfo info;
- ArrayList list;
+ public ArrayList list;
+ public bool FreeThreaded = true;
internal MethodBinder () {
// this.info = null;
@@ -38,6 +39,10 @@
this.list.Add(mi);
}
+ public int Count {
+ get { return this.list.Count; }
+ }
+
internal void AddMethod(MethodBase m) {
// if more than one, use complex ds, else use info
this.list.Add(m);
@@ -98,6 +103,9 @@
return IntPtr.Zero;
}
+ //Console.WriteLine("\nrelease: {0}", binding.info);
+ PythonEngine.ReleaseThreadLock();
+
try {
result = binding.info.Invoke(binding.inst,
BindingFlags.Default,
@@ -109,9 +117,16 @@
if (e.InnerException != null) {
e = e.InnerException;
}
+
+ //Console.WriteLine("\nacquire: {0}", binding.info);
+ PythonEngine.AcquireThreadLock();
+
Exceptions.SetError(e);
return IntPtr.Zero;
}
+
+ //Console.WriteLine("\nacquire: {0}", binding.info);
+ PythonEngine.AcquireThreadLock();
MethodInfo mi = (MethodInfo)binding.info;
return Converter.ToPython(result, mi.ReturnType);
=== PythonNet/src/runtime/PropertyObject.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/PropertyObject.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/PropertyObject.cs Mon Jul 28 22:28:15 2003
@@ -43,8 +43,10 @@
public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) {
PropertyObject self = (PropertyObject)GetManagedObject(ds);
MethodInfo getter = self.getter;
+ IntPtr ts = IntPtr.Zero;
Object result;
+
if (getter == null) {
Exceptions.SetError(Exceptions.TypeError,
"property cannot be read"
@@ -67,11 +69,14 @@
);
return IntPtr.Zero;
}
+ //ts = PythonEngine.BeginAllowThreads();
try {
result = self.info.GetValue(null, null);
+ // PythonEngine.EndAllowThreads(ts);
return Converter.ToPython(result, self.info.PropertyType);
}
catch(Exception e) {
+ // PythonEngine.EndAllowThreads(ts);
Exceptions.SetError(Exceptions.TypeError, e.Message);
return IntPtr.Zero;
}
@@ -79,10 +84,15 @@
try {
CLRObject co = (CLRObject)GetManagedObject(ob);
+ //ts = PythonEngine.BeginAllowThreads();
result = self.info.GetValue(co.inst, null);
+ // PythonEngine.EndAllowThreads(ts);
return Converter.ToPython(result, self.info.PropertyType);
}
catch(Exception e) {
+ //if (ts != IntPtr.Zero) {
+ // PythonEngine.EndAllowThreads(ts);
+ //}
Exceptions.SetError(Exceptions.TypeError, e.Message);
return IntPtr.Zero;
}
@@ -98,6 +108,7 @@
public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) {
PropertyObject self = (PropertyObject)GetManagedObject(ds);
MethodInfo setter = self.setter;
+ IntPtr ts = IntPtr.Zero;
Object newval;
if (val == IntPtr.Zero) {
@@ -140,14 +151,21 @@
try {
if (!is_static) {
CLRObject co = (CLRObject)GetManagedObject(ob);
+ //ts = PythonEngine.BeginAllowThreads();
self.info.SetValue(co.inst, newval, null);
+ //PythonEngine.EndAllowThreads(ts);
}
else {
+ //ts = PythonEngine.BeginAllowThreads();
self.info.SetValue(null, newval, null);
+ //PythonEngine.EndAllowThreads(ts);
}
return 0;
}
catch(Exception e) {
+ //if (ts != IntPtr.Zero) {
+ // PythonEngine.EndAllowThreads(ts);
+ //}
Exceptions.SetError(Exceptions.TypeError, e.Message);
return -1;
}
=== PythonNet/src/runtime/PythonException.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/PythonException.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/PythonException.cs Mon Jul 28 22:28:15 2003
@@ -14,11 +14,8 @@
namespace Python.Runtime {
/// <summary>
- /// Provides an interface to exceptions thrown by the Python runtime.
- ///
- /// Managed wrappers for the Python APIs will propagate exceptions
- /// thrown in the Python runtime by throwing a PythonException that
- /// wraps and provides access to the Python exception information.
+ /// Provides a managed interface to exceptions thrown by the Python
+ /// runtime.
/// </summary>
public class PythonException : System.Exception {
@@ -28,31 +25,12 @@
private IntPtr excTb = IntPtr.Zero;
public PythonException() : base() {
- // According to the SDK docs, because IntPtr is blittable the
- // interop marshaller will pin automatically for byref calls.
Runtime.PyErr_Fetch(ref excType, ref excValue, ref excTb);
+ Runtime.Incref(excType);
+ Runtime.Incref(excValue);
+ Runtime.Incref(excTb);
}
- /// <summary>
- /// Traceback Property
- /// </summary>
- ///
- /// <remarks>
- /// Returns the message associated with the exception.
- /// </remarks>
-
- string _message;
-
- public override string Message {
- get {
- if (_message != null) {
- return _message;
- }
- IntPtr ob = Runtime.PyObject_Str(excValue);
- _message = Runtime.PyString_AsString(ob);
- return _message;
- }
- }
/// <summary>
/// Type Property
@@ -64,7 +42,7 @@
public IntPtr Type {
get {
- return IntPtr.Zero;
+ return excType;
}
}
@@ -78,7 +56,7 @@
public IntPtr Value {
get {
- return IntPtr.Zero;
+ return excValue;
}
}
@@ -92,7 +70,7 @@
public IntPtr Traceback {
get {
- return IntPtr.Zero;
+ return excTb;
}
}
=== PythonNet/src/runtime/Runtime.cs 1.1 => 1.2 ===
--- PythonNet/src/runtime/Runtime.cs:1.1 Mon Jul 14 15:59:51 2003
+++ PythonNet/src/runtime/Runtime.cs Mon Jul 28 22:28:15 2003
@@ -98,17 +98,20 @@
// TODO: get rid of this! This works around the gc crash
// until I have time to dig into it.
+ bool hack = true;
- IntPtr nm = Runtime.PyString_FromString("gc");
- IntPtr md = Runtime.PyImport_Import(nm);
- IntPtr fn = Runtime.PyObject_GetAttrString(md, "disable");
- IntPtr aa = Runtime.PyTuple_New(0);
- IntPtr rr = Runtime.PyObject_Call(fn, aa, IntPtr.Zero);
- Runtime.Decref(rr);
- Runtime.Decref(aa);
- Runtime.Decref(fn);
- Runtime.Decref(nm);
- Runtime.Decref(md);
+ if (hack) {
+ IntPtr nm = Runtime.PyString_FromString("gc");
+ IntPtr md = Runtime.PyImport_Import(nm);
+ IntPtr fn = Runtime.PyObject_GetAttrString(md, "disable");
+ IntPtr aa = Runtime.PyTuple_New(0);
+ IntPtr rr = Runtime.PyObject_Call(fn, aa, IntPtr.Zero);
+ Runtime.Decref(rr);
+ Runtime.Decref(aa);
+ Runtime.Decref(fn);
+ Runtime.Decref(nm);
+ Runtime.Decref(md);
+ }
}
internal unsafe static void Incref(IntPtr op) {
@@ -227,10 +230,20 @@
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
ExactSpelling=true, CharSet=CharSet.Ansi)]
internal unsafe static extern IntPtr
+ PyThreadState_New(IntPtr istate);
+
+ [DllImport("python22", CallingConvention=CallingConvention.Cdecl,
+ ExactSpelling=true, CharSet=CharSet.Ansi)]
+ internal unsafe static extern IntPtr
PyThreadState_Get();
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
ExactSpelling=true, CharSet=CharSet.Ansi)]
+ internal unsafe static extern IntPtr
+ PyThreadState_Swap(IntPtr tstate);
+
+ [DllImport("python22", CallingConvention=CallingConvention.Cdecl,
+ ExactSpelling=true, CharSet=CharSet.Ansi)]
public unsafe static extern int
Py_Main(int argc, string[] argv);
@@ -455,6 +468,10 @@
+ internal static bool PyInt_Check(IntPtr ob) {
+ return PyObject_Type(ob) == Runtime.PyIntType;
+ }
+
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
ExactSpelling=true, CharSet=CharSet.Ansi)]
internal unsafe static extern IntPtr
@@ -476,6 +493,10 @@
PyInt_GetMax();
+ internal static bool PyLong_Check(IntPtr ob) {
+ return PyObject_Type(ob) == Runtime.PyLongType;
+ }
+
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
ExactSpelling=true, CharSet=CharSet.Ansi)]
internal unsafe static extern IntPtr
@@ -689,8 +710,8 @@
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
EntryPoint="PyUnicodeUCS2_AsUnicode",
- ExactSpelling=true, CharSet=CharSet.Unicode)]
- internal unsafe static extern string
+ ExactSpelling=true)]
+ internal unsafe static extern char *
PyUnicode_AsUnicode(IntPtr ob);
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
@@ -704,15 +725,18 @@
internal unsafe static extern IntPtr
PyUnicode_FromOrdinal(int c);
- internal static string GetManagedString(IntPtr op) {
+ internal unsafe static string GetManagedString(IntPtr op) {
IntPtr type = PyObject_Type(op);
if (type == Runtime.PyStringType) {
return Runtime.PyString_AsString(op);
}
if (type == Runtime.PyUnicodeType) {
- return Runtime.PyUnicode_AsUnicode(op);
+ char *p = Runtime.PyUnicode_AsUnicode(op);
+ int size = Runtime.PyUnicode_GetSize(op);
+ return new String(p, 0, size);
}
return null;
+
}
@@ -861,6 +885,10 @@
// Python tuple methods
+
+ internal static bool PyTuple_Check(IntPtr ob) {
+ return PyObject_Type(ob) == Runtime.PyTupleType;
+ }
[DllImport("python22", CallingConvention=CallingConvention.Cdecl,
ExactSpelling=true, CharSet=CharSet.Ansi)]
=== PythonNet/src/runtime/TypeManager.cs 1.2 => 1.3 ===
--- PythonNet/src/runtime/TypeManager.cs:1.2 Thu Jul 24 19:55:00 2003
+++ PythonNet/src/runtime/TypeManager.cs Mon Jul 28 22:28:15 2003
@@ -89,6 +89,7 @@
if (! (name.StartsWith("tp_") ||
name.StartsWith("nb_") ||
name.StartsWith("sq_") ||
+ name.StartsWith("mp_") ||
name.StartsWith("bf_")
) ) {
continue;
@@ -200,6 +201,7 @@
if (i > -1) {
name = name.Substring(i + 1);
}
+
// todo - can blit this after first time!
PyTypeObject pyTypeObj = new PyTypeObject();
=== Removed File PythonNet/src/runtime/PythonInterpreter.cs ===