@@ -12,6 +12,17 @@ import (
12
12
"strings"
13
13
)
14
14
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
+
15
26
func (g * pyGen ) recurse (gotype types.Type , prefix , name string ) {
16
27
switch t := gotype .(type ) {
17
28
case * types.Basic :
@@ -61,11 +72,8 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
61
72
nargs := 0
62
73
nres := len (res )
63
74
npyres := nres
64
- rvHasErr := false // set to true if the main return is an error
65
75
if fsym .haserr {
66
- if NoPyExceptions {
67
- rvHasErr = true
68
- } else {
76
+ if ! NoPyExceptions {
69
77
npyres -= 1
70
78
}
71
79
}
@@ -160,27 +168,16 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
160
168
goRet := ""
161
169
if npyres == 0 {
162
170
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.
181
173
g .pybuild .Printf ("retval('PyObject*', caller_owns_return=True)" )
182
174
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 )
184
181
for i := 0 ; i < npyres ; i ++ {
185
182
sret := current .symtype (res [i ].GoType ())
186
183
if sret == nil {
@@ -189,11 +186,16 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
189
186
res [i ].Name (),
190
187
))
191
188
}
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"
195
193
}
196
194
}
195
+
196
+ g .pybuild .Printf ("retval(%s%s)" , strings .Join (pyrets , ", " ), ownership )
197
+
198
+ goRet = strings .Join (gorets , ", " )
197
199
if npyres > 1 {
198
200
goRet = "(" + goRet + ")"
199
201
}
@@ -471,7 +473,30 @@ if __err != nil {
471
473
}
472
474
}
473
475
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
+ }
475
500
} else {
476
501
g .gofile .Printf ("if boolPyToGo(goRun) {\n " )
477
502
g .gofile .Indent ()
0 commit comments