@@ -131,6 +131,9 @@ func getterMethod(self *C.PyObject, _closure unsafe.Pointer, methodId C.int) *C.
131131
132132 fieldType := field .Type ()
133133 if fieldType .Kind () == reflect .Ptr && fieldType .Elem ().Kind () == reflect .Struct {
134+ if field .IsNil () {
135+ return C .Py_None
136+ }
134137 if pyType , ok := maps .pyTypes [fieldType .Elem ()]; ok {
135138 newWrapper := allocWrapper ((* C .PyTypeObject )(unsafe .Pointer (pyType )), field .Interface ())
136139 if newWrapper == nil {
@@ -187,15 +190,24 @@ func setterMethod(self, value *C.PyObject, _closure unsafe.Pointer, methodId C.i
187190
188191 fieldType := field .Type ()
189192 if fieldType .Kind () == reflect .Ptr && fieldType .Elem ().Kind () == reflect .Struct {
193+ if C .Py_Is (value , C .Py_None ) != 0 {
194+ field .Set (reflect .Zero (fieldType ))
195+ return 0
196+ }
190197 if C .Py_IS_TYPE (value , & C .PyDict_Type ) != 0 {
191198 if field .IsNil () {
192199 field .Set (reflect .New (fieldType .Elem ()))
193200 }
194201 if ! ToValue (FromPy (value ), field .Elem ()) {
195- SetError (fmt .Errorf ("failed to convert dict to %s" , fieldType .Elem ()))
202+ SetTypeError (fmt .Errorf ("failed to convert dict to %s" , fieldType .Elem ()))
196203 return - 1
197204 }
198205 } else {
206+ pyType := C .Py_TYPE (value )
207+ if _ , ok := maps .typeMetas [(* C .PyObject )(unsafe .Pointer (pyType ))]; ! ok {
208+ SetTypeError (fmt .Errorf ("invalid value of type %v for struct pointer field" , FromPy ((* C .PyObject )(unsafe .Pointer (pyType )))))
209+ return - 1
210+ }
199211 valueWrapper := (* wrapperType )(unsafe .Pointer (value ))
200212 if valueWrapper == nil {
201213 SetError (fmt .Errorf ("invalid value for struct pointer field" ))
@@ -207,25 +219,30 @@ func setterMethod(self, value *C.PyObject, _closure unsafe.Pointer, methodId C.i
207219 } else if field .Kind () == reflect .Struct {
208220 if C .Py_IS_TYPE (value , & C .PyDict_Type ) != 0 {
209221 if ! ToValue (FromPy (value ), field ) {
210- SetError (fmt .Errorf ("failed to convert dict to %s" , field .Type ()))
222+ SetTypeError (fmt .Errorf ("failed to convert dict to %s" , field .Type ()))
211223 return - 1
212224 }
213225 } else {
226+ pyType := (* C .PyTypeObject )(unsafe .Pointer (value .ob_type ))
227+ if _ , ok := maps .typeMetas [(* C .PyObject )(unsafe .Pointer (pyType ))]; ! ok {
228+ SetTypeError (fmt .Errorf ("invalid value of type %v for struct field" , FromPy ((* C .PyObject )(unsafe .Pointer (pyType )))))
229+ return - 1
230+ }
214231 valueWrapper := (* wrapperType )(unsafe .Pointer (value ))
215232 if valueWrapper == nil {
216233 SetError (fmt .Errorf ("invalid value for struct field" ))
217234 return - 1
218235 }
219236 baseAddr := goPtr .UnsafePointer ()
220237 fieldAddr := unsafe .Add (baseAddr , typeMeta .typ .Field (methodMeta .index ).Offset )
221- fieldPtr := reflect .NewAt (fieldType , fieldAddr ). Interface ()
222- reflect . ValueOf ( fieldPtr ).Set (reflect .ValueOf (valueWrapper .goObj ))
238+ fieldPtr := reflect .NewAt (fieldType , fieldAddr )
239+ fieldPtr . Elem ( ).Set (reflect .ValueOf (valueWrapper .goObj ). Elem ( ))
223240 }
224241 return 0
225242 }
226243
227244 if ! ToValue (FromPy (value ), field ) {
228- SetError (fmt .Errorf ("failed to convert value to %s" , methodMeta .typ ))
245+ SetTypeError (fmt .Errorf ("failed to convert value to %s" , methodMeta .typ ))
229246 return - 1
230247 }
231248 return 0
0 commit comments