@@ -50,6 +50,7 @@ type slotMeta struct {
5050 hasRecv bool // whether it has a receiver
5151 index int // used for member type
5252 typ reflect.Type // member/method type
53+ def * C.PyMethodDef
5354}
5455
5556type typeMeta struct {
@@ -60,9 +61,7 @@ type typeMeta struct {
6061
6162func allocWrapper (typ * C.PyTypeObject , obj any ) * wrapperType {
6263 self := C .PyType_GenericAlloc (typ , 0 )
63- if self == nil {
64- return nil
65- }
64+ check (self != nil , "failed to allocate wrapper" )
6665 wrapper := (* wrapperType )(unsafe .Pointer (self ))
6766 holder := new (objectHolder )
6867 holder .obj = obj
@@ -83,9 +82,7 @@ func wrapperAlloc(typ *C.PyTypeObject, size C.Py_ssize_t) *C.PyObject {
8382 maps := getGlobalData ()
8483 meta := maps .typeMetas [(* C .PyObject )(unsafe .Pointer (typ ))]
8584 wrapper := allocWrapper (typ , reflect .New (meta .typ ).Interface ())
86- if wrapper == nil {
87- return nil
88- }
85+ check (wrapper != nil , "failed to allocate wrapper" )
8986 return (* C .PyObject )(unsafe .Pointer (wrapper ))
9087}
9188
@@ -101,9 +98,8 @@ func wrapperInit(self, args *C.PyObject) C.int {
10198 typ := (* C .PyObject )(self ).ob_type
10299 maps := getGlobalData ()
103100 typeMeta := maps .typeMetas [(* C .PyObject )(unsafe .Pointer (typ ))]
104- if typeMeta .init == nil {
105- return 0
106- }
101+ check (typeMeta != nil , "type not registered" )
102+ check (typeMeta .init != nil , "init method not found" )
107103 if wrapperMethod_ (typeMeta , typeMeta .init , self , args , 0 ) == nil {
108104 return - 1
109105 }
@@ -114,15 +110,9 @@ func wrapperInit(self, args *C.PyObject) C.int {
114110func getterMethod (self * C.PyObject , _closure unsafe.Pointer , methodId C.int ) * C.PyObject {
115111 maps := getGlobalData ()
116112 typeMeta := maps .typeMetas [(* C .PyObject )(unsafe .Pointer (self .ob_type ))]
117- if typeMeta == nil {
118- SetError (fmt .Errorf ("type %v not registered" , FromPy (self )))
119- return nil
120- }
113+ check (typeMeta != nil , fmt .Sprintf ("type %v not registered" , FromPy (self )))
121114 methodMeta := typeMeta .methods [uint (methodId )]
122- if methodMeta == nil {
123- SetError (fmt .Errorf ("getter method %d not found" , methodId ))
124- return nil
125- }
115+ check (methodMeta != nil , fmt .Sprintf ("getter method %d not found" , methodId ))
126116
127117 wrapper := (* wrapperType )(unsafe .Pointer (self ))
128118 goPtr := reflect .ValueOf (wrapper .goObj )
@@ -136,10 +126,7 @@ func getterMethod(self *C.PyObject, _closure unsafe.Pointer, methodId C.int) *C.
136126 }
137127 if pyType , ok := maps .pyTypes [fieldType .Elem ()]; ok {
138128 newWrapper := allocWrapper ((* C .PyTypeObject )(unsafe .Pointer (pyType )), field .Interface ())
139- if newWrapper == nil {
140- SetError (fmt .Errorf ("failed to allocate wrapper for nested struct pointer" ))
141- return nil
142- }
129+ check (newWrapper != nil , "failed to allocate wrapper for nested struct pointer" )
143130 return (* C .PyObject )(unsafe .Pointer (newWrapper ))
144131 }
145132 } else if field .Kind () == reflect .Struct {
@@ -148,10 +135,7 @@ func getterMethod(self *C.PyObject, _closure unsafe.Pointer, methodId C.int) *C.
148135 fieldAddr := unsafe .Add (baseAddr , typeMeta .typ .Field (methodMeta .index ).Offset )
149136 fieldPtr := reflect .NewAt (fieldType , fieldAddr ).Interface ()
150137 newWrapper := allocWrapper ((* C .PyTypeObject )(unsafe .Pointer (pyType )), fieldPtr )
151- if newWrapper == nil {
152- SetError (fmt .Errorf ("failed to allocate wrapper for nested struct" ))
153- return nil
154- }
138+ check (newWrapper != nil , "failed to allocate wrapper for nested struct" )
155139 return (* C .PyObject )(unsafe .Pointer (newWrapper ))
156140 }
157141 }
@@ -162,29 +146,23 @@ func getterMethod(self *C.PyObject, _closure unsafe.Pointer, methodId C.int) *C.
162146func setterMethod (self , value * C.PyObject , _closure unsafe.Pointer , methodId C.int ) C.int {
163147 maps := getGlobalData ()
164148 typeMeta := maps .typeMetas [(* C .PyObject )(unsafe .Pointer (self .ob_type ))]
165- if typeMeta == nil {
166- SetError (fmt .Errorf ("type %v not registered" , FromPy (self )))
167- return - 1
168- }
149+ check (typeMeta != nil , fmt .Sprintf ("type %v not registered" , FromPy (self )))
169150 methodMeta := typeMeta .methods [uint (methodId )]
170- if methodMeta == nil {
171- SetError (fmt .Errorf ("setter method %d not found" , methodId ))
172- return - 1
173- }
151+ check (methodMeta != nil , fmt .Sprintf ("setter method %d not found" , methodId ))
174152
175153 wrapper := (* wrapperType )(unsafe .Pointer (self ))
176154 goPtr := reflect .ValueOf (wrapper .goObj )
177155 goValue := goPtr .Elem ()
178156
179157 structValue := goValue
180158 if ! structValue .CanSet () {
181- SetError (fmt .Errorf ("struct value cannot be set" ))
159+ SetTypeError (fmt .Errorf ("struct value cannot be set" ))
182160 return - 1
183161 }
184162
185163 field := structValue .Field (methodMeta .index )
186164 if ! field .CanSet () {
187- SetError (fmt .Errorf ("field %s cannot be set" , methodMeta .name ))
165+ SetTypeError (fmt .Errorf ("field %s cannot be set" , methodMeta .name ))
188166 return - 1
189167 }
190168
@@ -210,7 +188,7 @@ func setterMethod(self, value *C.PyObject, _closure unsafe.Pointer, methodId C.i
210188 }
211189 valueWrapper := (* wrapperType )(unsafe .Pointer (value ))
212190 if valueWrapper == nil {
213- SetError (fmt .Errorf ("invalid value for struct pointer field" ))
191+ SetTypeError (fmt .Errorf ("invalid value for struct pointer field" ))
214192 return - 1
215193 }
216194 field .Set (reflect .ValueOf (valueWrapper .goObj ))
@@ -229,10 +207,6 @@ func setterMethod(self, value *C.PyObject, _closure unsafe.Pointer, methodId C.i
229207 return - 1
230208 }
231209 valueWrapper := (* wrapperType )(unsafe .Pointer (value ))
232- if valueWrapper == nil {
233- SetError (fmt .Errorf ("invalid value for struct field" ))
234- return - 1
235- }
236210 baseAddr := goPtr .UnsafePointer ()
237211 fieldAddr := unsafe .Add (baseAddr , typeMeta .typ .Field (methodMeta .index ).Offset )
238212 fieldPtr := reflect .NewAt (fieldType , fieldAddr )
@@ -257,21 +231,13 @@ func wrapperMethod(self, args *C.PyObject, methodId C.int) *C.PyObject {
257231
258232 maps := getGlobalData ()
259233 typeMeta , ok := maps .typeMetas [key ]
260- if ! ok {
261- SetError (fmt .Errorf ("type %v not registered" , FromPy (key )))
262- return nil
263- }
234+ check (ok , fmt .Sprintf ("type %v not registered" , FromPy (key )))
264235
265236 methodMeta := typeMeta .methods [uint (methodId )]
266237 return wrapperMethod_ (typeMeta , methodMeta , self , args , methodId )
267238}
268239
269240func wrapperMethod_ (typeMeta * typeMeta , methodMeta * slotMeta , self , args * C.PyObject , methodId C.int ) * C.PyObject {
270- if methodMeta == nil {
271- SetError (fmt .Errorf ("method %d not found" , methodId ))
272- return nil
273- }
274-
275241 methodType := methodMeta .typ
276242 argc := C .PyTuple_Size (args )
277243 expectedArgs := methodType .NumIn ()
@@ -550,9 +516,11 @@ func (m Module) AddType(obj, init any, name, doc string) Object {
550516 * currentSlot = slot
551517 }
552518
519+ typeName := fmt .Sprintf ("%s.%s" , m .Name (), name )
520+
553521 totalSize := unsafe .Sizeof (wrapperType {})
554522 spec := & C.PyType_Spec {
555- name : C .CString (name ),
523+ name : C .CString (typeName ),
556524 basicsize : C .int (totalSize ),
557525 flags : C .Py_TPFLAGS_DEFAULT ,
558526 slots : slotsPtr ,
@@ -627,30 +595,30 @@ func (m Module) AddMethod(name string, fn any, doc string) Func {
627595 }
628596
629597 methodId := uint (len (meta .methods ))
630- meta .methods [methodId ] = & slotMeta {
598+
599+ methodPtr := C .wrapperMethods [methodId ]
600+ cName := C .CString (name )
601+ cDoc := C .CString (doc )
602+
603+ def := (* C .PyMethodDef )(C .malloc (C .size_t (unsafe .Sizeof (C.PyMethodDef {}))))
604+ def .ml_name = cName
605+ def .ml_meth = C .PyCFunction (methodPtr )
606+ def .ml_flags = C .METH_VARARGS
607+ def .ml_doc = cDoc
608+
609+ methodMeta := & slotMeta {
631610 name : name ,
632611 methodName : name ,
633612 fn : fn ,
634613 typ : t ,
635614 doc : doc ,
636615 hasRecv : false ,
616+ def : def ,
637617 }
638-
639- methodPtr := C .wrapperMethods [methodId ]
640- cName := C .CString (name )
641- cDoc := C .CString (doc )
642-
643- def := & C.PyMethodDef {
644- ml_name : cName ,
645- ml_meth : C .PyCFunction (methodPtr ),
646- ml_flags : C .METH_VARARGS ,
647- ml_doc : cDoc ,
648- }
618+ meta .methods [methodId ] = methodMeta
649619
650620 pyFunc := C .PyCFunction_NewEx (def , m .obj , m .obj )
651- if pyFunc == nil {
652- panic (fmt .Sprintf ("Failed to create function %s" , name ))
653- }
621+ check (pyFunc != nil , fmt .Sprintf ("Failed to create function %s" , name ))
654622
655623 if C .PyModule_AddObjectRef (m .obj , cName , pyFunc ) < 0 {
656624 C .Py_DecRef (pyFunc )
@@ -660,12 +628,6 @@ func (m Module) AddMethod(name string, fn any, doc string) Func {
660628 return newFunc (pyFunc )
661629}
662630
663- func SetError (err error ) {
664- errStr := C .CString (err .Error ())
665- C .PyErr_SetString (C .PyExc_RuntimeError , errStr )
666- C .free (unsafe .Pointer (errStr ))
667- }
668-
669631func SetTypeError (err error ) {
670632 errStr := C .CString (err .Error ())
671633 C .PyErr_SetString (C .PyExc_TypeError , errStr )
0 commit comments