@@ -70,22 +70,9 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo
7070 // Primitive types do not have constructors, but they look like
7171 // they do from Python. If the ClassObject represents one of the
7272 // convertible primitive types, just convert the arg directly.
73- if ( type . IsPrimitive || type == typeof ( string ) )
73+ if ( type . IsPrimitive )
7474 {
75- if ( Runtime . PyTuple_Size ( args ) != 1 )
76- {
77- Exceptions . SetError ( Exceptions . TypeError , "no constructors match given arguments" ) ;
78- return default ;
79- }
80-
81- BorrowedReference op = Runtime . PyTuple_GetItem ( args , 0 ) ;
82-
83- if ( ! Converter . ToManaged ( op , type , out var result , true ) )
84- {
85- return default ;
86- }
87-
88- return CLRObject . GetReference ( result ! , tp ) ;
75+ return NewPrimitive ( tp , args , type ) ;
8976 }
9077
9178 if ( type . IsAbstract )
@@ -99,6 +86,11 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo
9986 return NewEnum ( type , args , tp ) ;
10087 }
10188
89+ if ( type == typeof ( string ) )
90+ {
91+ return NewString ( args , tp ) ;
92+ }
93+
10294 if ( IsGenericNullable ( type ) )
10395 {
10496 // Nullable<T> has special handling in .NET runtime.
@@ -112,6 +104,101 @@ static NewReference tp_new_impl(BorrowedReference tp, BorrowedReference args, Bo
112104 return self . NewObjectToPython ( obj , tp ) ;
113105 }
114106
107+ /// <summary>
108+ /// Construct a new .NET String object from Python args
109+ /// </summary>
110+ private static NewReference NewString ( BorrowedReference args , BorrowedReference tp )
111+ {
112+ if ( Runtime . PyTuple_Size ( args ) == 1 )
113+ {
114+ BorrowedReference ob = Runtime . PyTuple_GetItem ( args , 0 ) ;
115+ if ( Runtime . PyString_Check ( ob ) )
116+ {
117+ if ( Runtime . GetManagedString ( ob ) is string val )
118+ return CLRObject . GetReference ( val , tp ) ;
119+ }
120+
121+ // TODO: Initialise using constructors instead
122+
123+ Exceptions . SetError ( Exceptions . TypeError , "no constructors match given arguments" ) ;
124+ return default ;
125+ }
126+
127+ return default ;
128+ }
129+
130+ /// <summary>
131+ /// Create a new Python object for a primitive type
132+ ///
133+ /// The primitive types are Boolean, Byte, SByte, Int16, UInt16,
134+ /// Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double,
135+ /// and Single.
136+ ///
137+ /// All numeric types and Boolean can be handled by a simple
138+ /// conversion, (U)IntPtr has to be handled separately as we
139+ /// do not want to convert them automically to/from integers.
140+ /// </summary>
141+ /// <param name="type">.NET type to construct</param>
142+ /// <param name="tp">Corresponding Python type</param>
143+ /// <param name="args">Constructor arguments</param>
144+ private static NewReference NewPrimitive ( BorrowedReference tp , BorrowedReference args , Type type )
145+ {
146+ // TODO: Handle IntPtr
147+ if ( Runtime . PyTuple_Size ( args ) != 1 )
148+ {
149+ Exceptions . SetError ( Exceptions . TypeError , "no constructors match given arguments" ) ;
150+ return default ;
151+ }
152+
153+ BorrowedReference op = Runtime . PyTuple_GetItem ( args , 0 ) ;
154+ object ? result = null ;
155+
156+ if ( type == typeof ( IntPtr ) )
157+ {
158+ if ( ManagedType . GetManagedObject ( op ) is CLRObject clrObject )
159+ {
160+ switch ( clrObject . inst )
161+ {
162+ case nint val :
163+ result = new IntPtr ( val ) ;
164+ break ;
165+ case Int64 val :
166+ result = new IntPtr ( val ) ;
167+ break ;
168+ case Int32 val :
169+ result = new IntPtr ( val ) ;
170+ break ;
171+ }
172+ }
173+ }
174+
175+ if ( type == typeof ( UIntPtr ) )
176+ {
177+ if ( ManagedType . GetManagedObject ( op ) is CLRObject clrObject )
178+ {
179+ switch ( clrObject . inst )
180+ {
181+ case nuint val :
182+ result = new UIntPtr ( val ) ;
183+ break ;
184+ case UInt64 val :
185+ result = new UIntPtr ( val ) ;
186+ break ;
187+ case UInt32 val :
188+ result = new UIntPtr ( val ) ;
189+ break ;
190+ }
191+ }
192+ }
193+
194+ if ( result == null && ! Converter . ToManaged ( op , type , out result , true ) )
195+ {
196+ return default ;
197+ }
198+
199+ return CLRObject . GetReference ( result ! , tp ) ;
200+ }
201+
115202 protected virtual void SetTypeNewSlot ( BorrowedReference pyType , SlotsHolder slotsHolder )
116203 {
117204 TypeManager . InitializeSlotIfEmpty ( pyType , TypeOffset . tp_new , new Interop . BBB_N ( tp_new_impl ) , slotsHolder ) ;
0 commit comments