8000 Add properties for accessing the object implementing an interface · weizx208/pythonnet@44c4e18 · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit 44c4e18

Browse files
committed
Add properties for accessing the object implementing an interface
1 parent a74664c commit 44c4e18

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

src/runtime/converter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ internal static IntPtr ToPython(object value, Type type)
176176
if (type.IsInterface)
177177
{
178178
var ifaceObj = (InterfaceObject)ClassManager.GetClass(type);
179-
return CLRObject.GetInstHandle(value, ifaceObj.pyHandle);
179+
return ifaceObj.WrapObject(value);
180180
}
181181

182182
// We need to special case interface array handling to ensure we

src/runtime/interfaceobject.cs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,43 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
7171
return IntPtr.Zero;
7272
}
7373

74-
return CLRObject.GetInstHandle(obj, self.pyHandle);
74+
return self.WrapObject(obj);
75+
}
76+
77+
/// <summary>
78+
/// Wrap the given object in an interface object, so that only methods
79+
/// of the interface are available.
80+
/// </summary>
81+
public IntPtr WrapObject(object impl)
82+
{
83+
var objPtr = CLRObject.GetInstHandle(impl, pyHandle);
84+
return objPtr;
85+
}
86+
87+
/// <summary>
88+
/// Expose the wrapped implementation through attributes in both
89+
/// converted/encoded (__implementation__) and raw (__raw_implementation__) form.
90+
/// </summary>
91+
public static IntPtr tp_getattro(IntPtr ob, IntPtr key)
92+
{
93+
var clrObj = (CLRObject)GetManagedObject(ob);
94+
95+
if (!Runtime.PyString_Check(key))
96+
{
97+
return Exceptions.RaiseTypeError("string expected");
98+
}
99+
100+
string name = Runtime.GetManagedString(key);
101+
if (name == "__implementation__")
102+
{
103+
return Converter.ToPython(clrObj.inst);
104+
}
105+
else if (name == "__raw_implementation__")
106+
{
107+
return CLRObject.GetInstHandle(clrObj.inst);
108+
}
109+
110+
return Runtime.PyObject_GenericGetAttr(ob, key);
75111
}
76112
}
77113
}

src/tests/test_interface.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def test_explicit_cast_to_interface():
6161
assert hasattr(i1, 'SayHello')
6262
assert i1.SayHello() == 'hello 1'
6363
assert not hasattr(i1, 'HelloProperty')
64+
assert i1.__implementation__ == ob
65+
assert i1.__raw_implementation__ == ob
6466

6567
i2 = Test.ISayHello2(ob)
6668
assert type(i2).__name__ == 'ISayHello2'
@@ -76,6 +78,7 @@ def test_interface_object_returned_through_method():
7678
ob = InterfaceTest()
7779
hello1 = ob.GetISayHello1()
7880
assert type(hello1).__name__ == 'ISayHello1'
81+
assert hello1.__implementation__.__class__.__name__ == "InterfaceTest"
7982

8083
assert hello1.SayHello() == 'hello 1'
8184

@@ -107,3 +110,13 @@ def test_interface_array_returned():
107110
ob = InterfaceTest()
108111
hellos = ob.GetISayHello1Array()
109112
assert type(hellos[0]).__name__ == 'ISayHello1'
113+
assert hellos[0].__implementation__.__class__.__name__ == "InterfaceTest"
114+
115+
def test_implementation_access():
116+
"""Test the __implementation__ and __raw_implementation__ properties"""
117+
import System
118+
clrVal = System.Int32(100)
119+
i = System.IComparable(clrVal)
120+
assert 100 == i.__implementation__
121+
assert clrVal == i.__raw_implementation__
122+
assert i.__implementation__ != i.__raw_implementation__

0 commit comments

Comments
 (0)
0