@@ -300,7 +300,7 @@ internal static int ArgPrecedence(Type t)
300300 /// <param name="args">The Python arguments.</param>
301301 /// <param name="kw">The Python keyword arguments.</param>
302302 /// <returns>A Binding if successful. Otherwise null.</returns>
303- internal Binding Bind ( IntPtr inst , IntPtr args , IntPtr kw )
303+ internal Binding Bind ( BorrowedReference inst , BorrowedReference args , BorrowedReference kw )
304304 {
305305 return Bind ( inst , args , kw , null , null ) ;
306306 }
@@ -316,7 +316,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw)
316316 /// <param name="kw">The Python keyword arguments.</param>
317317 /// <param name="info">If not null, only bind to that method.</param>
318318 /// <returns>A Binding if successful. Otherwise null.</returns>
319- internal Binding Bind ( IntPtr inst , IntPtr args , IntPtr kw , MethodBase info )
319+ internal Binding Bind ( BorrowedReference inst , BorrowedReference args , BorrowedReference kw , MethodBase info )
320320 {
321321 return Bind ( inst , args , kw , info , null ) ;
322322 }
@@ -363,24 +363,23 @@ public MismatchedMethod(Exception exception, MethodBase mb)
363363 /// <param name="info">If not null, only bind to that method.</param>
364364 /// <param name="methodinfo">If not null, additionally attempt to bind to the generic methods in this array by inferring generic type parameters.</param>
365365 /// <returns>A Binding if successful. Otherwise null.</returns>
366- internal Binding Bind ( IntPtr inst , IntPtr args , IntPtr kw , MethodBase info , MethodInfo [ ] methodinfo )
366+ internal Binding Bind ( BorrowedReference inst , BorrowedReference args , BorrowedReference kw , MethodBase info , MethodInfo [ ] methodinfo )
367367 {
368368 // loop to find match, return invoker w/ or w/o error
369369 MethodBase [ ] _methods = null ;
370370
371- var kwargDict = new Dictionary < string , IntPtr > ( ) ;
372- if ( kw != IntPtr . Zero )
371+ var kwargDict = new Dictionary < string , PyObject > ( ) ;
372+ if ( kw != null )
373373 {
374- var pynkwargs = ( int ) Runtime . PyDict_Size ( kw ) ;
375- IntPtr keylist = Runtime . PyDict_Keys ( kw ) ;
376- IntPtr valueList = Runtime . PyDict_Values ( kw ) ;
374+ nint pynkwargs = Runtime . PyDict_Size ( kw ) ;
375+ using var keylist = Runtime . PyDict_Keys ( kw ) ;
376+ using var valueList = Runtime . PyDict_Values ( kw ) ;
377377 for ( int i = 0 ; i < pynkwargs ; ++ i )
378378 {
379- var keyStr = Runtime . GetManagedString ( Runtime . PyList_GetItem ( new BorrowedReference ( keylist ) , i ) ) ;
380- kwargDict [ keyStr ] = Runtime . PyList_GetItem ( new BorrowedReference ( valueList ) , i ) . DangerousGetAddress ( ) ;
379+ var keyStr = Runtime . GetManagedString ( Runtime . PyList_GetItem ( keylist . Borrow ( ) , i ) ) ;
380+ BorrowedReference value = Runtime . PyList_GetItem ( valueList . Borrow ( ) , i ) ;
381+ kwargDict [ keyStr ] = new PyObject ( value ) ;
381382 }
382- Runtime . XDecref ( keylist ) ;
383- Runtime . XDecref ( valueList ) ;
384383 }
385384
386385 var pynargs = ( int ) Runtime . PyTuple_Size ( args ) ;
@@ -442,7 +441,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
442441 }
443442 if ( isOperator )
444443 {
445- if ( inst != IntPtr . Zero )
444+ if ( inst != null )
446445 {
447446 if ( ManagedType . GetManagedObject ( inst ) is CLRObject co )
448447 {
@@ -514,7 +513,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
514513 var mi = bestMatch . Method ;
515514
516515 object target = null ;
517- if ( ! mi . IsStatic && inst != IntPtr . Zero )
516+ if ( ! mi . IsStatic && inst != null )
518517 {
519518 //CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
520519 // InvalidCastException: Unable to cast object of type
@@ -561,33 +560,33 @@ static AggregateException GetAggregateException(IEnumerable<MismatchedMethod> mi
561560 return new AggregateException ( mismatchedMethods . Select ( m => new ArgumentException ( $ "{ m . Exception . Message } in method { m . Method } ", m . Exception ) ) ) ;
562561 }
563562
564- static IntPtr HandleParamsArray ( IntPtr args , int arrayStart , int pyArgCount , out bool isNewReference )
563+ static BorrowedReference HandleParamsArray ( BorrowedReference args , int arrayStart , int pyArgCount , out NewReference tempObject )
565564 {
566- isNewReference = false ;
567- IntPtr op ;
565+ BorrowedReference op ;
566+ tempObject = default ;
568567 // for a params method, we may have a sequence or single/multiple items
569568 // here we look to see if the item at the paramIndex is there or not
570569 // and then if it is a sequence itself.
571570 if ( ( pyArgCount - arrayStart ) == 1 )
572571 {
573572 // we only have one argument left, so we need to check it
574573 // to see if it is a sequence or a single item
575- IntPtr item = Runtime . PyTuple_GetItem ( args , arrayStart ) ;
574+ BorrowedReference item = Runtime . PyTuple_GetItem ( args , arrayStart ) ;
576575 if ( ! Runtime . PyString_Check ( item ) && Runtime . PySequence_Check ( item ) )
577576 {
578577 // it's a sequence (and not a string), so we use it as the op
579578 op = item ;
580579 }
581580 else
582581 {
583- isNewReference = true ;
584- op = Runtime . PyTuple_GetSlice ( args , arrayStart , pyArgCount ) ;
582+ tempObject = Runtime . PyTuple_GetSlice ( args , arrayStart , pyArgCount ) ;
583+ op = tempObject . Borrow ( ) ;
585584 }
586585 }
587586 else
588587 {
589- isNewReference = true ;
590- op = Runtime . PyTuple_GetSlice ( args , arrayStart , pyArgCount ) ;
588+ tempObject = Runtime . PyTuple_GetSlice ( args , arrayStart , pyArgCount ) ;
589+ op = tempObject . Borrow ( ) ;
591590 }
592591 return op ;
593592 }
@@ -607,8 +606,8 @@ static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out
607606 /// <param name="outs">Returns number of output parameters</param>
608607 /// <returns>If successful, an array of .NET arguments that can be passed to the method. Otherwise null.</returns>
609608 static object [ ] TryConvertArguments ( ParameterInfo [ ] pi , bool paramsArray ,
610- IntPtr args , int pyArgCount ,
611- Dictionary < string , IntPtr > kwargDict ,
609+ BorrowedReference args , int pyArgCount ,
610+ Dictionary < string , PyObject > kwargDict ,
612611 ArrayList defaultArgList ,
613612 out int outs )
614613 {
@@ -620,7 +619,6 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
620619 {
621620 var parameter = pi [ paramIndex ] ;
622621 bool hasNamedParam = parameter . Name != null ? kwargDict . ContainsKey ( parameter . Name ) : false ;
623- bool isNewReference = false ;
624622
625623 if ( paramIndex >= pyArgCount && ! ( hasNamedParam || ( paramsArray && paramIndex == arrayStart ) ) )
626624 {
@@ -632,7 +630,8 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
632630 continue ;
633631 }
634632
635- IntPtr op ;
633+ BorrowedReference op ;
634+ NewReference tempObject = default ;
636635 if ( hasNamedParam )
637636 {
638637 op = kwargDict [ parameter . Name ] ;
@@ -641,7 +640,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
641640 {
642641 if ( arrayStart == paramIndex )
643642 {
644- op = HandleParamsArray ( args , arrayStart , pyArgCount , out isNewReference ) ;
643+ op = HandleParamsArray ( args , arrayStart , pyArgCount , out tempObject ) ;
645644 }
646645 else
647646 {
@@ -652,16 +651,11 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
652651 bool isOut ;
653652 if ( ! TryConvertArgument ( op , parameter . ParameterType , out margs [ paramIndex ] , out isOut ) )
654653 {
654+ tempObject . Dispose ( ) ;
655655 return null ;
656656 }
657657
658- if ( isNewReference )
659- {
660- // TODO: is this a bug? Should this happen even if the conversion fails?
661- // GetSlice() creates a new reference but GetItem()
662- // returns only a borrow reference.
663- Runtime . XDecref ( op ) ;
664- }
658+ tempObject . Dispose ( ) ;
665659
666660 if ( isOut )
667661 {
@@ -681,7 +675,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
681675 /// <param name="arg">Converted argument.</param>
682676 /// <param name="isOut">Whether the CLR type is passed by reference.</param>
683677 /// <returns>true on success</returns>
684- static bool TryConvertArgument ( IntPtr op , Type parameterType ,
678+ static bool TryConvertArgument ( BorrowedReference op , Type parameterType ,
685679 out object arg , out bool isOut )
686680 {
687681 arg = null ;
@@ -707,22 +701,21 @@ static bool TryConvertArgument(IntPtr op, Type parameterType,
707701 /// <param name="parameterType">The parameter's managed type.</param>
708702 /// <param name="argument">Pointer to the Python argument object.</param>
709703 /// <returns>null if conversion is not possible</returns>
710- static Type TryComputeClrArgumentType ( Type parameterType , IntPtr argument )
704+ static Type TryComputeClrArgumentType ( Type parameterType , BorrowedReference argument )
711705 {
712706 // this logic below handles cases when multiple overloading methods
713707 // are ambiguous, hence comparison between Python and CLR types
714708 // is necessary
715709 Type clrtype = null ;
716- IntPtr pyoptype ;
717710
718711 if ( clrtype != null )
719712 {
720713 if ( ( parameterType != typeof ( object ) ) && ( parameterType != clrtype ) )
721714 {
722- IntPtr pytype = Converter . GetPythonTypeByAlias ( parameterType ) ;
723- pyoptype = Runtime . PyObject_Type ( argument ) ;
715+ BorrowedReference pytype = Converter . GetPythonTypeByAlias ( parameterType ) ;
716+ BorrowedReference pyoptype = Runtime . PyObject_TYPE ( argument ) ;
724717 var typematch = false ;
725- if ( pyoptype != IntPtr . Zero )
718+ if ( pyoptype != null )
726719 {
727720 if ( pytype != pyoptype )
728721 {
@@ -749,7 +742,6 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument)
749742 Exceptions . RaiseTypeError ( $ "Expected { parameterTypeCode } , got { clrTypeCode } ") ;
750743 }
751744 }
752- Runtime . XDecref ( pyoptype ) ;
753745 if ( ! typematch )
754746 {
755747 return null ;
@@ -779,7 +771,7 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument)
779771 /// <param name="defaultsNeeded">Number of non-null defaultsArgs.</param>
780772 /// <returns></returns>
781773 static bool MatchesArgumentCount ( int positionalArgumentCount , ParameterInfo [ ] parameters ,
782- Dictionary < string , IntPtr > kwargDict ,
774+ Dictionary < string , PyObject > kwargDict ,
783775 out bool paramsArray ,
784776 out ArrayList defaultArgList ,
785777 out int kwargsMatched ,
@@ -847,30 +839,29 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
847839 return Invoke ( inst , args , kw , info , null ) ;
848840 }
849841
850- protected static void AppendArgumentTypes ( StringBuilder to , IntPtr args )
842+ protected static void AppendArgumentTypes ( StringBuilder to , BorrowedReference args )
851843 {
852- long argCount = Runtime . PyTuple_Size ( args ) ;
844+ Runtime . AssertNoErorSet ( ) ;
845+
846+ nint argCount = Runtime . PyTuple_Size ( args ) ;
853847 to . Append ( "(" ) ;
854- for ( long argIndex = 0 ; argIndex < argCount ; argIndex ++ )
848+ for ( nint argIndex = 0 ; argIndex < argCount ; argIndex ++ )
855849 {
856- var arg = Runtime . PyTuple_GetItem ( args , argIndex ) ;
857- if ( arg != IntPtr . Zero )
850+ BorrowedReference arg = Runtime . PyTuple_GetItem ( args , argIndex ) ;
851+ if ( arg != null )
858852 {
859- var type = Runtime . PyObject_Type ( arg ) ;
860- if ( type != IntPtr . Zero )
853+ BorrowedReference type = Runtime . PyObject_TYPE ( arg ) ;
854+ if ( type != null )
861855 {
862- try
856+ using var description = Runtime . PyObject_Str ( type ) ;
857+ if ( description . IsNull ( ) )
863858 {
864- var description = Runtime . PyObject_Str ( type ) ;
865- if ( description != IntPtr . Zero )
866- {
867- to . Append ( Runtime . GetManagedString ( description ) ) ;
868- Runtime . XDecref ( description ) ;
869- }
859+ Exceptions . Clear ( ) ;
860+ to . Append ( Util . BadStr ) ;
870861 }
871- finally
862+ else
872863 {
873- Runtime . XDecref ( type ) ;
864+ to . Append ( Runtime . GetManagedString ( description . Borrow ( ) ) ) ;
874865 }
875866 }
876867 }
@@ -914,8 +905,7 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
914905 Runtime . PyErr_Fetch ( out var errType , out var errVal , out var errTrace ) ;
915906 AppendArgumentTypes ( to : value , args ) ;
916907 Runtime . PyErr_Restore ( errType . StealNullable ( ) , errVal . StealNullable ( ) , errTrace . StealNullable ( ) ) ;
917- Exceptions . RaiseTypeError ( value . ToString ( ) ) ;
918- return IntPtr . Zero ;
908+ return Exceptions . RaiseTypeError ( value . ToString ( ) ) ;
919909 }
920910
921911 if ( allow_threads )
@@ -938,7 +928,7 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
938928 PythonEngine . EndAllowThreads ( ts ) ;
939929 }
940930 Exceptions . SetError ( e ) ;
941- return IntPtr . Zero ;
931+ return default ;
942932 }
943933
944934 if ( allow_threads )
@@ -962,11 +952,11 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
962952
963953 bool isVoid = mi . ReturnType == typeof ( void ) ;
964954 int tupleSize = binding . outs + ( isVoid ? 0 : 1 ) ;
965- IntPtr t = Runtime . PyTuple_New ( tupleSize ) ;
955+ using var t = Runtime . PyTuple_New ( tupleSize ) ;
966956 if ( ! isVoid )
967957 {
968- IntPtr v = Converter . ToPython ( result , mi . ReturnType ) ;
969- Runtime . PyTuple_SetItem ( t , n , v ) ;
958+ using var v = Converter . ToPython ( result , mi . ReturnType ) ;
959+ Runtime . PyTuple_SetItem ( t . Borrow ( ) , n , v . Steal ( ) ) ;
970960 n ++ ;
971961 }
972962
@@ -975,21 +965,19 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
975965 Type pt = pi [ i ] . ParameterType ;
976966 if ( pt . IsByRef )
977967 {
978- IntPtr v = Converter . ToPython ( binding . args [ i ] , pt . GetElementType ( ) ) ;
979- Runtime . PyTuple_SetItem ( t , n , v ) ;
968+ using var v = Converter . ToPython ( binding . args [ i ] , pt . GetElementType ( ) ) ;
969+ Runtime . PyTuple_SetItem ( t . Borrow ( ) , n , v . Steal ( ) ) ;
980970 n ++ ;
981971 }
982972 }
983973
984974 if ( binding . outs == 1 && mi . ReturnType == typeof ( void ) )
985975 {
986- IntPtr v = Runtime . PyTuple_GetItem ( t , 0 ) ;
987- Runtime . XIncref ( v ) ;
988- Runtime . XDecref ( t ) ;
989- return v ;
976+ BorrowedReference item = Runtime . PyTuple_GetItem ( t . Borrow ( ) , 0 ) ;
977+ return new NewReference ( item ) ;
990978 }
991979
992- return t ;
980+ return new NewReference ( t . Borrow ( ) ) ;
993981 }
994982
995983 return Converter . ToPython ( result , mi . ReturnType ) ;
0 commit comments