| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e6eac73 commit 0bd8c47
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,6 +8,8 @@ | |||
| 8 | 8 | // ========================================================================== | |
| 9 | 9 | ||
| 10 | 10 | using System; | |
| 11 | + using System.Dynamic; | ||
| 12 | + using System.Linq.Expressions; | ||
| 11 | 13 | ||
| 12 | 14 | namespace Python.Runtime { | |
| 13 | 15 | ||
@@ -17,7 +19,7 @@ namespace Python.Runtime { | |||
| 17 | 19 | /// http://www.python.org/doc/current/api/object.html for details. | |
| 18 | 20 | /// </summary> | |
| 19 | 21 | ||
| 20 | - public class PyObject : IDisposable { | ||
| 22 | + public class PyObject : DynamicObject, IDisposable { | ||
| 21 | 23 | ||
| 22 | 24 | protected internal IntPtr obj = IntPtr.Zero; | |
| 23 | 25 | private bool disposed = false; | |
@@ -95,7 +97,7 @@ public static PyObject FromManagedObject(object ob) { | |||
| 95 | 97 | ||
| 96 | 98 | public object AsManagedObject(Type t) { | |
| 97 | 99 | Object result; | |
| 98 | - if (!Converter.ToManaged(this.Handle, t, out result, false)) { | ||
| 100 | + if (!Converter.ToManaged(this.obj, t, out result, false)) { | ||
| 99 | 101 | throw new InvalidCastException("cannot convert object to target type"); | |
| 100 | 102 | } | |
| 101 | 103 | return result; | |
@@ -609,7 +611,7 @@ public PyObject Invoke(PyTuple args) { | |||
| 609 | 611 | ||
| 610 | 612 | public PyObject Invoke(PyObject[] args, PyDict kw) { | |
| 611 | 613 | PyTuple t = new PyTuple(args); | |
| 612 | - IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw.obj); | ||
| 614 | + IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw != null ? kw.obj : IntPtr.Zero); | ||
| 613 | 615 | t.Dispose(); | |
| 614 | 616 | if (r == IntPtr.Zero) { | |
| 615 | 617 | throw new PythonException(); | |
@@ -628,7 +630,7 @@ public PyObject Invoke(PyObject[] args, PyDict kw) { | |||
| 628 | 630 | /// </remarks> | |
| 629 | 631 | ||
| 630 | 632 | public PyObject Invoke(PyTuple args, PyDict kw) { | |
| 631 | - IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw.obj); | ||
| 633 | + IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw != null ? kw.obj : IntPtr.Zero); | ||
| 632 | 634 | if (r == IntPtr.Zero) { | |
| 633 | 635 | throw new PythonException(); | |
| 634 | 636 | } | |
@@ -862,8 +864,222 @@ public override int GetHashCode() { | |||
| 862 | 864 | return Runtime.PyObject_Hash(obj).ToInt32(); | |
| 863 | 865 | } | |
| 864 | 866 | ||
| 867 | + public override bool TryGetMember(GetMemberBinder binder, out object result) | ||
| 868 | + { | ||
| 869 | + if (this.HasAttr(binder.Name)) | ||
| 870 | + { | ||
| 871 | + result = this.GetAttr(binder.Name); | ||
| 872 | + return true; | ||
| 873 | + } | ||
| 874 | + else | ||
| 875 | + return base.TryGetMember(binder, out result); | ||
| 876 | + } | ||
| 877 | + | ||
| 878 | + public override bool TrySetMember(SetMemberBinder binder, object value) | ||
| 879 | + { | ||
| 880 | + if (this.HasAttr(binder.Name)) | ||
| 881 | + { | ||
| 882 | + this.SetAttr(binder.Name, (PyObject)value); | ||
| 883 | + return true; | ||
| 884 | + } | ||
| 885 | + else | ||
| 886 | + return base.TrySetMember(binder, value); | ||
| 887 | + } | ||
| 888 | + | ||
| 889 | + private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs) | ||
| 890 | + { | ||
| 891 | + int arg_count; | ||
| 892 | + for (arg_count = 0; arg_count < inargs.Length && !(inargs[arg_count] is Py.KeywordArguments); ++arg_count); | ||
| 893 | + IntPtr argtuple = Runtime.PyTuple_New(arg_count); | ||
| 894 | + for (int i = 0; i < arg_count; i++) | ||
| 895 | + { | ||
| 896 | + IntPtr ptr; | ||
| 897 | + if (inargs[i] is PyObject) | ||
| 898 | + { | ||
| 899 | + ptr = ((PyObject)inargs[i]).Handle; | ||
| 900 | + Runtime.Incref(ptr); | ||
| 901 | + } | ||
| 902 | + else | ||
| 903 | + { | ||
| 904 | + ptr = Converter.ToPython(inargs[i], inargs[i].GetType()); | ||
| 905 | + } | ||
| 906 | + if (Runtime.PyTuple_SetItem(argtuple, i, ptr) < 0) | ||
| 907 | + throw new PythonException(); | ||
| 908 | + } | ||
| 909 | + args = new PyTuple(argtuple); | ||
| 910 | + kwargs = null; | ||
| 911 | + for (int i = arg_count; i < inargs.Length; i++) | ||
| 912 | + { | ||
| 913 | + if (!(inargs[i] is Py.KeywordArguments)) | ||
| 914 | + throw new ArgumentException("Keyword arguments must come after normal arguments."); | ||
| 915 | + if (kwargs == null) | ||
| 916 | + kwargs = (Py.KeywordArguments)inargs[i]; | ||
| 917 | + else | ||
| 918 | + kwargs.Update((Py.KeywordArguments)inargs[i]); | ||
| 919 | + } | ||
| 920 | + } | ||
| 865 | 921 | ||
| 922 | + public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) | ||
| 923 | + { | ||
| 924 | + if (this.HasAttr(binder.Name) && this.GetAttr(binder.Name).IsCallable()) | ||
| 925 | + { | ||
| 926 | + PyTuple pyargs; | ||
| 927 | + PyDict kwargs; | ||
| 928 | + GetArgs(args, out pyargs, out kwargs); | ||
| 929 | + result = InvokeMethod(binder.Name, pyargs, kwargs); | ||
| 930 | + return true; | ||
| 931 | + } | ||
| 932 | + else | ||
| 933 | + return base.TryInvokeMember(binder, args, out result); | ||
| 866 | 934 | } | |
| 867 | 935 | ||
| 936 | + public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) | ||
| 937 | + { | ||
| 938 | + if (this.IsCallable()) | ||
| 939 | + { | ||
| 940 | + PyTuple pyargs; | ||
| 941 | + PyDict kwargs; | ||
| 942 | + GetArgs(args, out pyargs, out kwargs); | ||
| 943 | + result = Invoke(pyargs, kwargs); | ||
| 944 | + return true; | ||
| 945 | + } | ||
| 946 | + else | ||
| 947 | + return base.TryInvoke(binder, args, out result); | ||
| 948 | + } | ||
| 949 | + | ||
| 950 | + public override bool TryConvert(ConvertBinder binder, out object result) | ||
| 951 | + { | ||
| 952 | + return Converter.ToManaged(this.obj, binder.Type, out result, false); | ||
| 953 | + } | ||
| 868 | 954 | ||
| 955 | + public override bool TryBinaryOperation(BinaryOperationBinder binder, Object arg, out Object result) { | ||
| 956 | + IntPtr res; | ||
| 957 | + if (!(arg is PyObject)) | ||
| 958 | + arg = arg.ToPython(); | ||
| 959 | + | ||
| 960 | + switch (binder.Operation) | ||
| 961 | + { | ||
| 962 | + case ExpressionType.Add: | ||
| 963 | + res = Runtime.PyNumber_Add(this.obj, ((PyObject)arg).obj); | ||
| 964 | + break; | ||
| 965 | + case ExpressionType.AddAssign: | ||
| 966 | + res = Runtime.PyNumber_InPlaceAdd(this.obj, ((PyObject)arg).obj); | ||
| 967 | + break; | ||
| 968 | + case ExpressionType.Subtract: | ||
| 969 | + res = Runtime.PyNumber_Subtract(this.obj, ((PyObject)arg).obj); | ||
| 970 | + break; | ||
| 971 | + case ExpressionType.SubtractAssign: | ||
| 972 | + res = Runtime.PyNumber_InPlaceSubtract(this.obj, ((PyObject)arg).obj); | ||
| 973 | + break; | ||
| 974 | + case ExpressionType.Multiply: | ||
| 975 | + res = Runtime.PyNumber_Multiply(this.obj, ((PyObject)arg).obj); | ||
| 976 | + break; | ||
| 977 | + case ExpressionType.MultiplyAssign: | ||
| 978 | + res = Runtime.PyNumber_InPlaceMultiply(this.obj, ((PyObject)arg).obj); | ||
| 979 | + break; | ||
| 980 | + case ExpressionType.Divide: | ||
| 981 | + res = Runtime.PyNumber_Divide(this.obj, ((PyObject)arg).obj); | ||
| 982 | + break; | ||
| 983 | + case ExpressionType.DivideAssign: | ||
| 984 | + res = Runtime.PyNumber_InPlaceDivide(this.obj, ((PyObject)arg).obj); | ||
| 985 | + break; | ||
| 986 | + case ExpressionType.And: | ||
| 987 | + res = Runtime.PyNumber_And(this.obj, ((PyObject)arg).obj); | ||
| 988 | + break; | ||
| 989 | + case ExpressionType.AndAssign: | ||
| 990 | + res = Runtime.PyNumber_InPlaceAnd(this.obj, ((PyObject)arg).obj); | ||
| 991 | + break; | ||
| 992 | + case ExpressionType.ExclusiveOr: | ||
| 993 | + res = Runtime.PyNumber_Xor(this.obj, ((PyObject)arg).obj); | ||
| 994 | + break; | ||
| 995 | + case ExpressionType.ExclusiveOrAssign: | ||
| 996 | + res = Runtime.PyNumber_InPlaceXor(this.obj, ((PyObject)arg).obj); | ||
| 997 | + break; | ||
| 998 | + case ExpressionType.GreaterThan: | ||
| 999 | + result = Runtime.PyObject_Compare(this.obj, ((PyObject)arg).obj) > 0; | ||
| 1000 | + return true; | ||
| 1001 | + case ExpressionType.GreaterThanOrEqual: | ||
| 1002 | + result = Runtime.PyObject_Compare(this.obj, ((PyObject)arg).obj) >= 0; | ||
| 1003 | + return true; | ||
| 1004 | + case ExpressionType.LeftShift: | ||
| 1005 | + res = Runtime.PyNumber_Lshift(this.obj, ((PyObject)arg).obj); | ||
| 1006 | + break; | ||
| 1007 | + case ExpressionType.LeftShiftAssign: | ||
| 1008 | + res = Runtime.PyNumber_InPlaceLshift(this.obj, ((PyObject)arg).obj); | ||
| 1009 | + break; | ||
| 1010 | + case ExpressionType.LessThan: | ||
| 1011 | + result = Runtime.PyObject_Compare(this.obj, ((PyObject)arg).obj) < 0; | ||
| 1012 | + return true; | ||
| 1013 | + case ExpressionType.LessThanOrEqual: | ||
| 1014 | + result = Runtime.PyObject_Compare(this.obj, ((PyObject)arg).obj) <= 0; | ||
| 1015 | + return true; | ||
| 1016 | + case ExpressionType.Modulo: | ||
| 1017 | + res = Runtime.PyNumber_Remainder(this.obj, ((PyObject)arg).obj); | ||
| 1018 | + break; | ||
| 1019 | + case ExpressionType.ModuloAssign: | ||
| 1020 | + res = Runtime.PyNumber_InPlaceRemainder(this.obj, ((PyObject)arg).obj); | ||
| 1021 | + break; | ||
| 1022 | + case ExpressionType.NotEqual: | ||
| 1023 | + result = Runtime.PyObject_Compare(this.obj, ((PyObject)arg).obj) != 0; | ||
| 1024 | + return true; | ||
| 1025 | + case ExpressionType.Or: | ||
| 1026 | + res = Runtime.PyNumber_Or(this.obj, ((PyObject)arg).obj); | ||
| 1027 | + break; | ||
| 1028 | + case ExpressionType.OrAssign: | ||
| 1029 | + res = Runtime.PyNumber_InPlaceOr(this.obj, ((PyObject)arg).obj); | ||
| 1030 | + break; | ||
| 1031 | + case ExpressionType.Power: | ||
| 1032 | + res = Runtime.PyNumber_Power(this.obj, ((PyObject)arg).obj); | ||
| 1033 | + break; | ||
| 1034 | + case ExpressionType.RightShift: | ||
| 1035 | + res = Runtime.PyNumber_Rshift(this.obj, ((PyObject)arg).obj); | ||
| 1036 | + break; | ||
| 1037 | + case ExpressionType.RightShiftAssign: | ||
| 1038 | + res = Runtime.PyNumber_InPlaceRshift(this.obj, ((PyObject)arg).obj); | ||
| 1039 | + break; | ||
| 1040 | + default: | ||
| 1041 | + result = null; | ||
| 1042 | + return false; | ||
| 1043 | + } | ||
| 1044 | + result = new PyObject(res); | ||
| 1045 | + return true; | ||
| 1046 | + } | ||
| 1047 | + | ||
| 1048 | + public override bool TryUnaryOperation(UnaryOperationBinder binder, out Object result) | ||
| 1049 | + { | ||
| 1050 | + int r; | ||
| 1051 | + IntPtr res; | ||
| 1052 | + switch (binder.Operation) | ||
| 1053 | + { | ||
| 1054 | + case ExpressionType.Negate: | ||
| 1055 | + res = Runtime.PyNumber_Negative(this.obj); | ||
| 1056 | + break; | ||
| 1057 | + case ExpressionType.UnaryPlus: | ||
| 1058 | + res = Runtime.PyNumber_Positive(this.obj); | ||
| 1059 | + break; | ||
| 1060 | + case ExpressionType.OnesComplement: | ||
| 1061 | + res = Runtime.PyNumber_Invert(this.obj); | ||
| 1062 | + break; | ||
| 1063 | + case ExpressionType.Not: | ||
| 1064 | + r = Runtime.PyObject_Not(this.obj); | ||
| 1065 | + result = r == 1; | ||
| 1066 | + return r != -1; | ||
| 1067 | + case ExpressionType.IsFalse: | ||
| 1068 | + r = Runtime.PyObject_IsTrue(this.obj); | ||
| 1069 | + result = r == 0; | ||
| 1070 | + return r != -1; | ||
| 1071 | + case ExpressionType.IsTrue: | ||
| 1072 | + r = Runtime.PyObject_IsTrue(this.obj); | ||
| 1073 | + result = r == 1; | ||
| 1074 | + return r != -1; | ||
| 1075 | + case ExpressionType.Decrement: | ||
| 1076 | + case ExpressionType.Increment: | ||
| 1077 | + default: | ||
| 1078 | + result = null; | ||
| 1079 | + return false; | ||
| 1080 | + } | ||
| 1081 | + result = new PyObject(res); | ||
| 1082 | + return true; | ||
| 1083 | + } | ||
| 1084 | + } | ||
| 869 | 1085 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments