@@ -303,6 +303,11 @@ internal static IntPtr ToPythonImplicit(object value)
303303 /// Return a managed object for the given Python object, taking funny
304304 /// byref types into account.
305305 /// </summary>
306+ /// <param name="value">A Python object</param>
307+ /// <param name="type">The desired managed type</param>
308+ /// <param name="result">Receives the managed object</param>
309+ /// <param name="setError">If true, call <c>Exceptions.SetError</c> with the reason for failure.</param>
310+ /// <returns>True on success</returns>
306311 internal static bool ToManaged ( IntPtr value , Type type ,
307312 out object result , bool setError )
308313 {
@@ -341,7 +346,10 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
341346 result = tmp ;
342347 return true ;
343348 }
344- Exceptions . SetError ( Exceptions . TypeError , $ "value cannot be converted to { obType } ") ;
349+ if ( setError )
350+ {
351+ Exceptions . SetError ( Exceptions . TypeError , $ "value cannot be converted to { obType } ") ;
352+ }
345353 return false ;
346354 }
347355 if ( mt is ClassBase )
@@ -376,6 +384,15 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
376384 obType = obType . GetGenericArguments ( ) [ 0 ] ;
377385 }
378386
387+ if ( obType . ContainsGenericParameters )
388+ {
389+ if ( setError )
390+ {
391+ Exceptions . SetError ( Exceptions . TypeError , $ "Cannot create an instance of the open generic type { obType } ") ;
392+ }
393+ return false ;
394+ }
395+
379396 if ( obType . IsArray )
380397 {
381398 return ToArray ( value , obType , out result , setError ) ;
@@ -777,7 +794,7 @@ private static void SetConversionError(IntPtr value, Type target)
777794 IntPtr ob = Runtime . PyObject_Repr ( value ) ;
778795 string src = Runtime . GetManagedString ( ob ) ;
779796 Runtime . XDecref ( ob ) ;
780- Exceptions . SetError ( Exceptions . TypeError , $ "Cannot convert { src } to { target } ") ;
797+ Exceptions . RaiseTypeError ( $ "Cannot convert { src } to { target } ") ;
781798 }
782799
783800
@@ -791,32 +808,58 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
791808 Type elementType = obType . GetElementType ( ) ;
792809 result = null ;
793810
794- bool IsSeqObj = Runtime . PySequence_Check ( value ) ;
795- var len = IsSeqObj ? Runtime . PySequence_Size ( value ) : - 1 ;
796-
797811 IntPtr IterObject = Runtime . PyObject_GetIter ( value ) ;
798-
799- if ( IterObject == IntPtr . Zero ) {
812+ if ( IterObject == IntPtr . Zero )
813+ {
800814 if ( setError )
801815 {
802816 SetConversionError ( value , obType ) ;
803817 }
818+ else
819+ {
820+ // PyObject_GetIter will have set an error
821+ Exceptions . Clear ( ) ;
822+ }
804823 return false ;
805824 }
806825
807- Array items ;
826+ IList list ;
827+ try
828+ {
829+ // MakeGenericType can throw because elementType may not be a valid generic argument even though elementType[] is a valid array type.
830+ // For example, if elementType is a pointer type.
831+ // See https://docs.microsoft.com/en-us/dotnet/api/system.type.makegenerictype#System_Type_MakeGenericType_System_Type
832+ var constructedListType = typeof ( List < > ) . MakeGenericType ( elementType ) ;
833+ bool IsSeqObj = Runtime . PySequence_Check ( value ) ;
834+ if ( IsSeqObj )
835+ {
836+ var len = Runtime . PySequence_Size ( value ) ;
837+ list = ( IList ) Activator . CreateInstance ( constructedListType , new Object [ ] { ( int ) len } ) ;
838+ }
839+ else
840+ {
841+ // CreateInstance can throw even if MakeGenericType succeeded.
842+ // See https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance#System_Activator_CreateInstance_System_Type_
843+ list = ( IList ) Activator . CreateInstance ( constructedListType ) ;
844+ }
845+ }
846+ catch ( Exception e )
847+ {
848+ if ( setError )
849+ {
850+ Exceptions . SetError ( e ) ;
851+ SetConversionError ( value , obType ) ;
852+ }
853+ return false ;
854+ }
808855
809- var listType = typeof ( List < > ) ;
810- var constructedListType = listType . MakeGenericType ( elementType ) ;
811- IList list = IsSeqObj ? ( IList ) Activator . CreateInstance ( constructedListType , new Object [ ] { ( int ) len } ) :
812- ( IList ) Activator . CreateInstance ( constructedListType ) ;
813856 IntPtr item ;
814857
815858 while ( ( item = Runtime . PyIter_Next ( IterObject ) ) != IntPtr . Zero )
816859 {
817- object obj = null ;
860+ object obj ;
818861
819- if ( ! Converter . ToManaged ( item , elementType , out obj , true ) )
862+ if ( ! Converter . ToManaged ( item , elementType , out obj , setError ) )
820863 {
821864 Runtime . XDecref ( item ) ;
822865 return false ;
@@ -827,7 +870,7 @@ private static bool ToArray(IntPtr value, Type obType, out object result, bool s
827870 }
828871 Runtime . XDecref ( IterObject ) ;
829872
830- items = Array . CreateInstance ( elementType , list . Count ) ;
873+ Array items = Array . CreateInstance ( elementType , list . Count ) ;
831874 list . CopyTo ( items , 0 ) ;
832875
833876 result = items ;
0 commit comments