@@ -15,6 +15,7 @@ public class TestOperator
1515 public void SetUp ( )
1616 {
1717 PythonEngine . Initialize ( ) ;
18+ OwnIntCodec . Setup ( ) ;
1819 }
1920
2021 [ OneTimeTearDown ]
@@ -23,6 +24,120 @@ public void Dispose()
2324 PythonEngine . Shutdown ( ) ;
2425 }
2526
27+ // Mock Integer class to test math ops on non-native dotnet types
28+ public struct OwnInt
29+ {
30+ private int _value ;
31+
32+ public int Num => _value ;
33+
34+ public OwnInt ( )
35+ {
36+ _value = 0 ;
37+ }
38+
39+ public OwnInt ( int value )
40+ {
41+ _value = value ;
42+ }
43+
44+ public static OwnInt operator - ( OwnInt p1 , OwnInt p2 )
45+ {
46+ return new OwnInt ( p1 . _value - p2 . _value ) ;
47+ }
48+
49+ public static OwnInt operator + ( OwnInt p1 , OwnInt p2 )
50+ {
51+ return new OwnInt ( p1 . _value + p2 . _value ) ;
52+ }
53+
54+ public static OwnInt operator * ( OwnInt p1 , OwnInt p2 )
55+ {
56+ return new OwnInt ( p1 . _value * p2 . _value ) ;
57+ }
58+
59+ public static OwnInt operator / ( OwnInt p1 , OwnInt p2 )
60+ {
61+ return new OwnInt ( p1 . _value / p2 . _value ) ;
62+ }
63+
64+ public static OwnInt operator % ( OwnInt p1 , OwnInt p2 )
65+ {
66+ return new OwnInt ( p1 . _value % p2 . _value ) ;
67+ }
68+
69+ public static OwnInt operator ^ ( OwnInt p1 , OwnInt p2 )
70+ {
71+ return new OwnInt ( p1 . _value ^ p2 . _value ) ;
72+ }
73+
74+ public static bool operator < ( OwnInt p1 , OwnInt p2 )
75+ {
76+ return p1 . _value < p2 . _value ;
77+ }
78+
79+ public static bool operator > ( OwnInt p1 , OwnInt p2 )
80+ {
81+ return p1 . _value > p2 . _value ;
82+ }
83+
84+ public static bool operator == ( OwnInt p1 , OwnInt p2 )
85+ {
86+ return p1 . _value == p2 . _value ;
87+ }
88+
89+ public static bool operator != ( OwnInt p1 , OwnInt p2 )
90+ {
91+ return p1 . _value != p2 . _value ;
92+ }
93+
94+ public static OwnInt operator | ( OwnInt p1 , OwnInt p2 )
95+ {
96+ return new OwnInt ( p1 . _value | p2 . _value ) ;
97+ }
98+
99+ public static OwnInt operator & ( OwnInt p1 , OwnInt p2 )
100+ {
101+ return new OwnInt ( p1 . _value & p2 . _value ) ;
102+ }
103+
104+ public static bool operator <= ( OwnInt p1 , OwnInt p2 )
105+ {
106+ return p1 . _value <= p2 . _value ;
107+ }
108+
109+ public static bool operator >= ( OwnInt p1 , OwnInt p2 )
110+ {
111+ return p1 . _value >= p2 . _value ;
112+ }
113+ }
114+
115+ // Codec for mock class above.
116+ public class OwnIntCodec : IPyObjectDecoder
117+ {
118+ public static void Setup ( )
119+ {
120+ PyObjectConversions . RegisterDecoder ( new OwnIntCodec ( ) ) ;
121+ }
122+
123+ public bool CanDecode ( PyType objectType , Type targetType )
124+ {
125+ return objectType . Name == "int" && targetType == typeof ( OwnInt ) ;
126+ }
127+
128+ public bool TryDecode < T > ( PyObject pyObj , out T ? value )
129+ {
130+ if ( pyObj . PyType . Name != "int" || typeof ( T ) != typeof ( OwnInt ) )
131+ {
132+ value = default ( T ) ;
133+ return false ;
134+ }
135+
136+ value = ( T ) ( object ) new OwnInt ( pyObj . As < int > ( ) ) ;
137+ return true ;
138+ }
139+ }
140+
26141 public class OperableObject
27142 {
28143 public int Num { get ; set ; }
@@ -524,6 +639,121 @@ public void ShiftOperatorOverloads()
524639
525640c = a >> b.Num
526641assert c.Num == a.Num >> b.Num
642+ " ) ;
643+ }
644+
645+ [ Test ]
646+ public void ReverseOperatorWithCodec ( )
647+ {
648+ string name = string . Format ( "{0}.{1}" ,
649+ typeof ( OwnInt ) . DeclaringType . Name ,
650+ typeof ( OwnInt ) . Name ) ;
651+ string module = MethodBase . GetCurrentMethod ( ) . DeclaringType . Namespace ;
652+
653+ PythonEngine . Exec ( $@ "
654+ from { module } import *
655+ cls = { name }
656+ a = 2
657+ b = cls(10)
658+
659+ c = a + b
660+ assert c.Num == a + b.Num
661+
662+ c = a - b
663+ assert c.Num == a - b.Num
664+
665+ c = a * b
666+ assert c.Num == a * b.Num
667+
668+ c = a / b
669+ assert c.Num == a // b.Num
670+
671+ c = a % b
672+ assert c.Num == a % b.Num
673+
674+ c = a & b
675+ assert c.Num == a & b.Num
676+
677+ c = a | b
678+ assert c.Num == a | b.Num
679+
680+ c = a ^ b
681+ assert c.Num == a ^ b.Num
682+
683+ c = a == b
684+ assert c == (a == b.Num)
685+
686+ c = a != b
687+ assert c == (a != b.Num)
688+
689+ c = a <= b
690+ assert c == (a <= b.Num)
691+
692+ c = a >= b
693+ assert c == (a >= b.Num)
694+
695+ c = a < b
696+ assert c == (a < b.Num)
697+
698+ c = a > b
699+ assert c == (a > b.Num)
700+ " ) ;
701+ }
702+
703+ [ Test ]
704+ public void ForwardOperatorWithCodec ( )
705+ {
706+ string name = string . Format ( "{0}.{1}" ,
707+ typeof ( OwnInt ) . DeclaringType . Name ,
708+ typeof ( OwnInt ) . Name ) ;
709+ string module = MethodBase . GetCurrentMethod ( ) . DeclaringType . Namespace ;
710+
711+ PythonEngine . Exec ( $@ "
712+ from { module } import *
713+ cls = { name }
714+ a = cls(2)
715+ b = 10
716+ c = a + b
717+ assert c.Num == a.Num + b
718+
719+ c = a - b
720+ assert c.Num == a.Num - b
721+
722+ c = a * b
723+ assert c.Num == a.Num * b
724+
725+ c = a / b
726+ assert c.Num == a.Num // b
727+
728+ c = a % b
729+ assert c.Num == a.Num % b
730+
731+ c = a & b
732+ assert c.Num == a.Num & b
733+
734+ c = a | b
735+ assert c.Num == a.Num | b
736+
737+ c = a ^ b
738+ assert c.Num == a.Num ^ b
739+
740+ c = a == b
741+ assert c == (a.Num == b)
742+
743+ c = a != b
744+ assert c == (a.Num != b)
745+
746+ c = a <= b
747+ assert c == (a.Num <= b)
748+
749+ c = a >= b
750+ assert c == (a.Num >= b)
751+
752+ c = a < b
753+ assert c == (a.Num < b)
754+
755+ c = a > b
756+ assert c == (a.Num > b)
527757" ) ;
528758 }
529759 }
0 commit comments