@@ -12,6 +12,17 @@ import (
1212 "strings"
1313)
1414
15+ func buildPyTuple (fsym * Func ) bool {
16+ npyres := len (fsym .sig .Results ())
17+ if fsym .haserr {
18+ if ! NoPyExceptions {
19+ npyres -= 1
20+ }
21+ }
22+
23+ return (npyres > 1 )
24+ }
25+
1526func (g * pyGen ) recurse (gotype types.Type , prefix , name string ) {
1627 switch t := gotype .(type ) {
1728 case * types.Basic :
@@ -61,11 +72,8 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
6172 nargs := 0
6273 nres := len (res )
6374 npyres := nres
64- rvHasErr := false // set to true if the main return is an error
6575 if fsym .haserr {
66- if NoPyExceptions {
67- rvHasErr = true
68- } else {
76+ if ! NoPyExceptions {
6977 npyres -= 1
7078 }
7179 }
@@ -160,27 +168,16 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
160168 goRet := ""
161169 if npyres == 0 {
162170 g .pybuild .Printf ("None" )
163- } else if npyres == 1 {
164- ret := res [0 ]
165- sret := current .symtype (ret .GoType ())
166- if sret == nil {
167- panic (fmt .Errorf (
168- "gopy: could not find symbol for %q" ,
169- ret .Name (),
170- ))
171- }
172-
173- if sret .cpyname == "PyObject*" {
174- g .pybuild .Printf ("retval('%s', caller_owns_return=True)" , sret .cpyname )
175- } else {
176- g .pybuild .Printf ("retval('%s')" , sret .cpyname )
177- }
178- goRet = fmt .Sprintf ("%s" , sret .cgoname )
179- } else {
180- // On Python side, we are returning PyTuple.
171+ } else if buildPyTuple (fsym ) {
172+ // We are returning PyTuple*. Setup pybindgen accordingly.
181173 g .pybuild .Printf ("retval('PyObject*', caller_owns_return=True)" )
182174
183- // On Go side, we are returning multiple values.
175+ // On Go side, return *C.PyObject.
176+ goRet = "unsafe.Pointer"
177+ } else {
178+ ownership := ""
179+ pyrets := make ([]string , npyres , npyres )
180+ gorets := make ([]string , npyres , npyres )
184181 for i := 0 ; i < npyres ; i ++ {
185182 sret := current .symtype (res [i ].GoType ())
186183 if sret == nil {
@@ -189,11 +186,16 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
189186 res [i ].Name (),
190187 ))
191188 }
192- goRet += sret .cgoname
193- if i != npyres - 1 {
194- goRet += ", "
189+ gorets [i ] = sret .cgoname
190+ pyrets [i ] = "'" + sret .cpyname + "'"
191+ if sret .cpyname == "PyObject*" {
192+ ownership = "caller_owns_return=True"
195193 }
196194 }
195+
196+ g .pybuild .Printf ("retval(%s%s)" , strings .Join (pyrets , ", " ), ownership )
197+
198+ goRet = strings .Join (gorets , ", " )
197199 if npyres > 1 {
198200 goRet = "(" + goRet + ")"
199201 }
@@ -471,7 +473,30 @@ if __err != nil {
471473 }
472474 }
473475
474- g .gofile .Printf ("return %s" , strings .Join (retvals [0 :npyres ], ", " ))
476+ if buildPyTuple (fsym ) {
477+ g .gofile .Printf ("\n " )
478+ formatStr := ""
479+ for i := 0 ; i < npyres ; i ++ {
480+ sret := current .symtype (res [i ].GoType ())
481+ if sret == nil {
482+ panic (fmt .Errorf (
483+ "gopy: could not find symbol for %q" ,
484+ res [i ].Name (),
485+ ))
486+ }
487+ if sret .pyfmt == "" {
488+ formatStr += "?"
489+ } else {
490+ formatStr += sret .pyfmt
491+ }
492+ }
493+ g .gofile .Printf ("return unsafe.Pointer(C.Py_BuildValue%d(\" %s\" , %s))\n " ,
494+ npyres ,
495+ formatStr ,
496+ strings .Join (retvals [0 :npyres ], ", " ))
497+ } else {
498+ g .gofile .Printf ("return %s\n " , strings .Join (retvals [0 :npyres ], ", " ))
499+ }
475500 } else {
476501 g .gofile .Printf ("if boolPyToGo(goRun) {\n " )
477502 g .gofile .Indent ()
0 commit comments