Skip to content

Commit 80fcbc4

Browse files
committed
Merge pull request #65 from medicomp/struct-default-constructor
Struct default constructor
2 parents 7eef624 + 403b60d commit 80fcbc4

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

src/runtime/classobject.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal class ClassObject : ClassBase {
2626

2727
internal ClassObject(Type tp) : base(tp) {
2828
ctors = type.GetConstructors();
29-
binder = new ConstructorBinder();
29+
binder = new ConstructorBinder(type);
3030

3131
for (int i = 0; i < ctors.Length; i++) {
3232
binder.AddMethod(ctors[i]);

src/runtime/constructorbinder.cs

+27-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ namespace Python.Runtime {
2121
//========================================================================
2222

2323
internal class ConstructorBinder : MethodBinder {
24+
private Type _containingType = null;
2425

25-
internal ConstructorBinder () : base() {}
26+
internal ConstructorBinder(Type containingType) : base() {
27+
_containingType = containingType;
28+
}
2629

2730
//====================================================================
2831
// Constructors get invoked when an instance of a wrapped managed
@@ -53,9 +56,31 @@ internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw) {
5356
/// </remarks>
5457
internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw,
5558
MethodBase info) {
56-
Binding binding = this.Bind(inst, args, kw, info);
5759
Object result;
5860

61+
if (_containingType.IsValueType && !_containingType.IsPrimitive &&
62+
!_containingType.IsEnum && _containingType != typeof (decimal) &&
63+
Runtime.PyTuple_Size(args) == 0) {
64+
// If you are trying to construct an instance of a struct by
65+
// calling its default constructor, that ConstructorInfo
66+
// instance will not appear in reflection and the object must
67+
// instead be constructed via a call to
68+
// Activator.CreateInstance().
69+
try {
70+
result = Activator.CreateInstance(_containingType);
71+
}
72+
catch (Exception e) {
73+
if (e.InnerException != null) {
74+
e = e.InnerException;
75+
}
76+
Exceptions.SetError(e);
77+
return null;
78+
}
79+
return result;
80+
}
81+
82+
Binding binding = this.Bind(inst, args, kw, info);
83+
5984
if (binding == null) {
6085
// It is possible for __new__ to be invoked on construction
6186
// of a Python subclass of a managed class, so args may

src/tests/test_class.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,9 @@ def testStructConstruction(self):
130130
"""Test construction of structs."""
131131
from System.Drawing import Point
132132

133-
def test():
134-
p = Point()
135-
136-
self.assertRaises(TypeError, test)
133+
p = Point()
134+
self.assertTrue(p.X == 0)
135+
self.assertTrue(p.Y == 0)
137136

138137
p = Point(0, 0)
139138
self.assertTrue(p.X == 0)

0 commit comments

Comments
 (0)