FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonnet/src/runtime/constructorbinder.cs at drop-python2 · filmor/pythonnet · GitHub
filmor
/
pythonnet
Public
forked from
pythonnet/pythonnet
Notifications
You must be signed in to change notification settings
Fork
1
Star
1
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonnet
/
src
/
runtime
/
constructorbinder.cs
Copy path
More file actions
More file actions
Latest commit
History
History
History
130 lines (119 loc) · 5.27 KB
Breadcrumbs
pythonnet
/
src
/
runtime
/
constructorbinder.cs
Copy path
File metadata and controls
130 lines (119 loc) · 5.27 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using
System
;
using
System
.
Reflection
;
using
System
.
Text
;
namespace
Python
.
Runtime
{
/// <summary>
/// A ConstructorBinder encapsulates information about one or more managed
/// constructors, and is responsible for selecting the right constructor
/// given a set of Python arguments. This is slightly different than the
/// standard MethodBinder because of a difference in invoking constructors
/// using reflection (which is seems to be a CLR bug).
/// </summary>
internal
class
ConstructorBinder
:
MethodBinder
{
private
Type
_containingType
;
internal
ConstructorBinder
(
Type
containingType
)
{
_containingType
=
containingType
;
}
/// <summary>
/// Constructors get invoked when an instance of a wrapped managed
/// class or a subclass of a managed class is created. This differs
/// from the MethodBinder implementation in that we return the raw
/// result of the constructor rather than wrapping it as a Python
/// object - the reason is that only the caller knows the correct
/// Python type to use when wrapping the result (may be a subclass).
/// </summary>
internal
object
InvokeRaw
(
IntPtr
inst
,
IntPtr
args
,
IntPtr
kw
)
{
return
InvokeRaw
(
inst
,
args
,
kw
,
null
)
;
}
/// <summary>
/// Allows ctor selection to be limited to a single attempt at a
/// match by providing the MethodBase to use instead of searching
/// the entire MethodBinder.list (generic ArrayList)
/// </summary>
/// <param name="inst"> (possibly null) instance </param>
/// <param name="args"> PyObject* to the arg tuple </param>
/// <param name="kw"> PyObject* to the keyword args dict </param>
/// <param name="info"> The sole ContructorInfo to use or null </param>
/// <returns> The result of the constructor call with converted params </returns>
/// <remarks>
/// 2010-07-24 BC: I added the info parameter to the call to Bind()
/// Binding binding = this.Bind(inst, args, kw, info);
/// to take advantage of Bind()'s ability to use a single MethodBase (CI or MI).
/// </remarks>
internal
object
InvokeRaw
(
IntPtr
inst
,
IntPtr
args
,
IntPtr
kw
,
MethodBase
info
)
{
object
result
;
if
(
_containingType
.
IsValueType
&&
!
_containingType
.
IsPrimitive
&&
!
_containingType
.
IsEnum
&&
_containingType
!=
typeof
(
decimal
)
&&
Runtime
.
PyTuple_Size
(
args
)
==
0
)
{
// If you are trying to construct an instance of a struct by
// calling its default constructor, that ConstructorInfo
// instance will not appear in reflection and the object must
// instead be constructed via a call to
// Activator.CreateInstance().
try
{
result
=
Activator
.
CreateInstance
(
_containingType
)
;
}
catch
(
Exception
e
)
{
if
(
e
.
InnerException
!=
null
)
{
e
=
e
.
InnerException
;
}
Exceptions
.
SetError
(
e
)
;
return
null
;
}
return
result
;
}
Binding
binding
=
Bind
(
inst
,
args
,
kw
,
info
)
;
if
(
binding
==
null
)
{
// It is possible for __new__ to be invoked on construction
// of a Python subclass of a managed class, so args may
// reflect more args than are required to instantiate the
// class. So if we cant find a ctor that matches, we'll see
// if there is a default constructor and, if so, assume that
// any extra args are intended for the subclass' __init__.
IntPtr
eargs
=
Runtime
.
PyTuple_New
(
0
)
;
binding
=
Bind
(
inst
,
eargs
,
kw
)
;
Runtime
.
XDecref
(
eargs
)
;
if
(
binding
==
null
)
{
var
errorMessage
=
new
StringBuilder
(
"No constructor matches given arguments"
)
;
if
(
info
!=
null
&&
info
.
IsConstructor
&&
info
.
DeclaringType
!=
null
)
{
errorMessage
.
Append
(
" for "
)
.
Append
(
info
.
DeclaringType
.
Name
)
;
}
errorMessage
.
Append
(
": "
)
;
AppendArgumentTypes
(
to
:
errorMessage
,
args
)
;
Exceptions
.
SetError
(
Exceptions
.
TypeError
,
errorMessage
.
ToString
(
)
)
;
return
null
;
}
}
// Fire the selected ctor and catch errors...
var
ci
=
(
ConstructorInfo
)
binding
.
info
;
// Object construction is presumed to be non-blocking and fast
// enough that we shouldn't really need to release the GIL.
try
{
result
=
ci
.
Invoke
(
binding
.
args
)
;
}
catch
(
Exception
e
)
{
if
(
e
.
InnerException
!=
null
)
{
e
=
e
.
InnerException
;
}
Exceptions
.
SetError
(
e
)
;
return
null
;
}
return
result
;
}
}
}
Back
|
FazBrowse Home
|
New Git URL