@@ -203,9 +203,43 @@ func GoPyMainRun() {
203
203
# File is generated by gopy. Do not edit.
204
204
# %[2]s
205
205
206
- from pybindgen import retval, param, Module
206
+ from pybindgen import retval, param, Function, Module
207
207
import sys
208
208
209
+ class CheckedFunction(Function):
210
+ def __init__(self, *a, **kw):
211
+ super(CheckedFunction, self).__init__(*a, **kw)
212
+ self._failure_expression = kw.get('failure_expression', '')
213
+ self._failure_cleanup = kw.get('failure_cleanup', '')
214
+
215
+ def set_failure_expression(self, expr):
216
+ self._failure_expression = expr
217
+
218
+ def set_failure_cleanup(self, expr):
219
+ self._failure_cleanup = expr
220
+
221
+ def generate_call(self):
222
+ super(CheckedFunction, self).generate_call()
223
+ check = "PyErr_Occurred()"
224
+ if self._failure_expression:
225
+ check = "{} && {}".format(self._failure_expression, check)
226
+ failure_cleanup = self._failure_cleanup or None
227
+ self.before_call.write_error_check(check, failure_cleanup)
228
+
229
+ def add_checked_function(mod, name, retval, params, failure_expression='', *a, **kw):
230
+ fn = CheckedFunction(name, retval, params, *a, **kw)
231
+ fn.set_failure_expression(failure_expression)
232
+ mod._add_function_obj(fn)
233
+ return fn
234
+
235
+ def add_checked_string_function(mod, name, retval, params, failure_expression='', *a, **kw):
236
+ fn = CheckedFunction(name, retval, params, *a, **kw)
237
+ fn.set_failure_cleanup('if (retval != NULL) free(retval);')
238
+ fn.after_call.add_cleanup_code('free(retval);')
239
+ fn.set_failure_expression(failure_expression)
240
+ mod._add_function_obj(fn)
241
+ return fn
242
+
209
243
mod = Module('_%[1]s')
210
244
mod.add_include('"%[1]s_go.h"')
211
245
mod.add_function('GoPyInit', None, [])
@@ -226,6 +260,11 @@ mod.add_function('NumHandles', retval('int'), [])
226
260
227
261
# the following is required to enable dlopen to open the _go.so file
228
262
import os,sys,inspect,collections
263
+ try:
264
+ import collections.abc as _collections_abc
265
+ except ImportError:
266
+ _collections_abc = collections
267
+
229
268
cwd = os.getcwd()
230
269
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
231
270
os.chdir(currentdir)
@@ -250,6 +289,10 @@ os.chdir(cwd)
250
289
# %[2]s
251
290
252
291
import collections
292
+ try:
293
+ import collections.abc as _collections_abc
294
+ except ImportError:
295
+ _collections_abc = collections
253
296
%[6]s
254
297
255
298
# to use this code in your end-user python file, import it as follows:
@@ -263,6 +306,10 @@ import collections
263
306
264
307
GoPkgDefs = `
265
308
import collections
309
+ try:
310
+ import collections.abc as _collections_abc
311
+ except ImportError:
312
+ _collections_abc = collections
266
313
267
314
class GoClass(object):
268
315
"""GoClass is the base class for all GoPy wrapper classes"""
@@ -317,8 +364,6 @@ build:
317
364
# use pybindgen to build the %[1]s.c file which are the CPython wrappers to cgo wrappers..
318
365
# note: pip install pybindgen to get pybindgen if this fails
319
366
$(PYTHON) build.py
320
- # patch storage leaks in pybindgen output
321
- go run patch-leaks.go %[1]s.c
322
367
# build the _%[1]s$(LIBEXT) library that contains the cgo and CPython wrappers
323
368
# generated %[1]s.py python wrapper imports this c-code package
324
369
$(GCC) %[1]s.c %[6]s %[1]s_go$(LIBEXT) -o _%[1]s$(LIBEXT) $(CFLAGS) $(LDFLAGS) -fPIC --shared -w
@@ -360,91 +405,11 @@ build:
360
405
# use pybindgen to build the %[1]s.c file which are the CPython wrappers to cgo wrappers..
361
406
# note: pip install pybindgen to get pybindgen if this fails
362
407
$(PYTHON) build.py
363
- # patch storage leaks in pybindgen output
364
- go run patch-leaks.go %[1]s.c
365
408
# build the executable
366
409
- rm %[1]s_go$(LIBEXT)
367
410
$(GOBUILD) -o py%[1]s
368
411
369
412
`
370
-
371
- patchLeaksPreamble = `// patch-leaks.go for post-processing %[1]s.
372
- // File is generated by gopy. Do not edit.
373
- // %[2]s
374
- // +build ignore
375
-
376
- package main
377
-
378
- import (
379
- "bufio"
380
- "bytes"
381
- "io/ioutil"
382
- "log"
383
- "os"
384
- "strings"
385
- )
386
-
387
- const (
388
- cStringLine = " py_retval = Py_BuildValue((char *) \"s\", retval);"
389
- )
390
- var cstringFunctions = []string{
391
- `
392
-
393
- patchLeaksPostamble = `
394
- }
395
-
396
- func isCString(line string, names []string) bool {
397
- for _, cfn := range names {
398
- if strings.HasPrefix(line, cfn) {
399
- return true
400
- }
401
- }
402
- return false
403
- }
404
-
405
- func patchCString(line string, out *bytes.Buffer) bool {
406
- out.WriteString(line)
407
- out.Write([]byte{'\n'})
408
- switch line {
409
- case "}":
410
- return false
411
- case cStringLine:
412
- out.WriteString(" free(retval);\n")
413
- return false
414
- }
415
- return true
416
- }
417
-
418
- func main() {
419
- file := os.Args[1]
420
- buf, err := ioutil.ReadFile(file)
421
- if err != nil {
422
- log.Fatal(err)
423
- }
424
- sc := bufio.NewScanner(bytes.NewBuffer(buf))
425
- obuf := &bytes.Buffer{}
426
- var cstring bool
427
- for sc.Scan() {
428
- line := sc.Text()
429
- if cstring {
430
- cstring = patchCString(line, obuf)
431
- continue
432
- }
433
- cstring = isCString(line, cstringFunctions)
434
- obuf.WriteString(line)
435
- obuf.Write([]byte{'\n'})
436
- }
437
-
438
- if err := sc.Err(); err != nil {
439
- log.Fatal(err)
440
- }
441
-
442
- err = ioutil.WriteFile(file, obuf.Bytes(), 0644)
443
- if err != nil {
444
- log.Fatal(err)
445
- }
446
- }
447
- `
448
413
)
449
414
450
415
// thePyGen is the current pyGen which is needed in symbols to lookup
@@ -536,7 +501,6 @@ func (g *pyGen) genPre() {
536
501
g .makefile = & printer {buf : new (bytes.Buffer ), indentEach : []byte ("\t " )}
537
502
}
538
503
g .genGoPreamble ()
539
- g .genLeaksPreamble ()
540
504
g .genPyBuildPreamble ()
541
505
if ! NoMake {
542
506
g .genMakefile ()
@@ -559,9 +523,7 @@ func (g *pyGen) genPrintOut(outfn string, pr *printer) {
559
523
func (g * pyGen ) genOut () {
560
524
g .pybuild .Printf ("\n mod.generate(open('%v.c', 'w'))\n \n " , g .cfg .Name )
561
525
g .gofile .Printf ("\n \n " )
562
- g .genLeaksPostamble ()
563
526
g .genPrintOut (g .cfg .Name + ".go" , g .gofile )
564
- g .genPrintOut ("patch-leaks.go" , g .leakfile )
565
527
g .genPrintOut ("build.py" , g .pybuild )
566
528
if ! NoMake {
567
529
g .makefile .Printf ("\n \n " )
@@ -635,14 +597,6 @@ func (g *pyGen) genGoPreamble() {
635
597
g .gofile .Printf ("\n // --- generated code for package: %[1]s below: ---\n \n " , g .cfg .Name )
636
598
}
637
599
638
- func (g * pyGen ) genLeaksPreamble () {
639
- g .leakfile .Printf (patchLeaksPreamble , g .cfg .Name , g .cfg .Cmd )
640
- }
641
-
642
- func (g * pyGen ) genLeaksPostamble () {
643
- g .leakfile .Printf (patchLeaksPostamble )
644
- }
645
-
646
600
func (g * pyGen ) genPyBuildPreamble () {
647
601
g .pybuild .Printf (PyBuildPreamble , g .cfg .Name , g .cfg .Cmd )
648
602
}
0 commit comments