@@ -210,23 +210,37 @@ class CheckedFunction(Function):
210
210
def __init__(self, *a, **kw):
211
211
super(CheckedFunction, self).__init__(*a, **kw)
212
212
self._failure_expression = kw.get('failure_expression', '')
213
+ self._failure_cleanup = kw.get('failure_cleanup', '')
213
214
214
215
def set_failure_expression(self, expr):
215
216
self._failure_expression = expr
216
217
218
+ def set_failure_cleanup(self, expr):
219
+ self._failure_cleanup = expr
220
+
217
221
def generate_call(self):
218
222
super(CheckedFunction, self).generate_call()
219
223
check = "PyErr_Occurred()"
220
224
if self._failure_expression:
221
225
check = "{} && {}".format(self._failure_expression, check)
222
- self.before_call.write_error_check(check)
226
+ failure_cleanup = self._failure_cleanup or None
227
+ self.before_call.write_error_check(check, failure_cleanup)
223
228
224
229
def add_checked_function(mod, name, retval, params, failure_expression='', *a, **kw):
225
230
fn = CheckedFunction(name, retval, params, *a, **kw)
226
231
fn.set_failure_expression(failure_expression)
227
232
mod._add_function_obj(fn)
228
233
return fn
229
234
235
+ def add_checked_string_function(mod, name, retval, params, failure_expression='', *a, **kw):
236
+ fn = CheckedFunction(name, retval, params, *a, **kw)
237
+ cleanup = 'free(retval);'
238
+ fn.set_failure_cleanup(cleanup)
239
+ fn.after_call.add_cleanup_code(cleanup)
240
+ fn.set_failure_expression(failure_expression)
241
+ mod._add_function_obj(fn)
242
+ return fn
243
+
230
244
mod = Module('_%[1]s')
231
245
mod.add_include('"%[1]s_go.h"')
232
246
mod.add_function('GoPyInit', None, [])
@@ -351,8 +365,6 @@ build:
351
365
# use pybindgen to build the %[1]s.c file which are the CPython wrappers to cgo wrappers..
352
366
# note: pip install pybindgen to get pybindgen if this fails
353
367
$(PYTHON) build.py
354
- # patch storage leaks in pybindgen output
355
- go run patch-leaks.go %[1]s.c
356
368
# build the _%[1]s$(LIBEXT) library that contains the cgo and CPython wrappers
357
369
# generated %[1]s.py python wrapper imports this c-code package
358
370
$(GCC) %[1]s.c %[6]s %[1]s_go$(LIBEXT) -o _%[1]s$(LIBEXT) $(CFLAGS) $(LDFLAGS) -fPIC --shared -w
@@ -394,91 +406,11 @@ build:
394
406
# use pybindgen to build the %[1]s.c file which are the CPython wrappers to cgo wrappers..
395
407
# note: pip install pybindgen to get pybindgen if this fails
396
408
$(PYTHON) build.py
397
- # patch storage leaks in pybindgen output
398
- go run patch-leaks.go %[1]s.c
399
409
# build the executable
400
410
- rm %[1]s_go$(LIBEXT)
401
411
$(GOBUILD) -o py%[1]s
402
412
403
413
`
404
-
405
- patchLeaksPreamble = `// patch-leaks.go for post-processing %[1]s.
406
- // File is generated by gopy. Do not edit.
407
- // %[2]s
408
- // +build ignore
409
-
410
- package main
411
-
412
- import (
413
- "bufio"
414
- "bytes"
415
- "io/ioutil"
416
- "log"
417
- "os"
418
- "strings"
419
- )
420
-
421
- const (
422
- cStringLine = " py_retval = Py_BuildValue((char *) \"s\", retval);"
423
- )
424
- var cstringFunctions = []string{
425
- `
426
-
427
- patchLeaksPostamble = `
428
- }
429
-
430
- func isCString(line string, names []string) bool {
431
- for _, cfn := range names {
432
- if strings.HasPrefix(line, cfn) {
433
- return true
434
- }
435
- }
436
- return false
437
- }
438
-
439
- func patchCString(line string, out *bytes.Buffer) bool {
440
- out.WriteString(line)
441
- out.Write([]byte{'\n'})
442
- switch line {
443
- case "}":
444
- return false
445
- case cStringLine:
446
- out.WriteString(" free(retval);\n")
447
- return false
448
- }
449
- return true
450
- }
451
-
452
- func main() {
453
- file := os.Args[1]
454
- buf, err := ioutil.ReadFile(file)
455
- if err != nil {
456
- log.Fatal(err)
457
- }
458
- sc := bufio.NewScanner(bytes.NewBuffer(buf))
459
- obuf := &bytes.Buffer{}
460
- var cstring bool
461
- for sc.Scan() {
462
- line := sc.Text()
463
- if cstring {
464
- cstring = patchCString(line, obuf)
465
- continue
466
- }
467
- cstring = isCString(line, cstringFunctions)
468
- obuf.WriteString(line)
469
- obuf.Write([]byte{'\n'})
470
- }
471
-
472
- if err := sc.Err(); err != nil {
473
- log.Fatal(err)
474
- }
475
-
476
- err = ioutil.WriteFile(file, obuf.Bytes(), 0644)
477
- if err != nil {
478
- log.Fatal(err)
479
- }
480
- }
481
- `
482
414
)
483
415
484
416
// thePyGen is the current pyGen which is needed in symbols to lookup
@@ -570,7 +502,6 @@ func (g *pyGen) genPre() {
570
502
g .makefile = & printer {buf : new (bytes.Buffer ), indentEach : []byte ("\t " )}
571
503
}
572
504
g .genGoPreamble ()
573
- g .genLeaksPreamble ()
574
505
g .genPyBuildPreamble ()
575
506
if ! NoMake {
576
507
g .genMakefile ()
@@ -593,9 +524,7 @@ func (g *pyGen) genPrintOut(outfn string, pr *printer) {
593
524
func (g * pyGen ) genOut () {
594
525
g .pybuild .Printf ("\n mod.generate(open('%v.c', 'w'))\n \n " , g .cfg .Name )
595
526
g .gofile .Printf ("\n \n " )
596
- g .genLeaksPostamble ()
597
527
g .genPrintOut (g .cfg .Name + ".go" , g .gofile )
598
- g .genPrintOut ("patch-leaks.go" , g .leakfile )
599
528
g .genPrintOut ("build.py" , g .pybuild )
600
529
if ! NoMake {
601
530
g .makefile .Printf ("\n \n " )
@@ -669,14 +598,6 @@ func (g *pyGen) genGoPreamble() {
669
598
g .gofile .Printf ("\n // --- generated code for package: %[1]s below: ---\n \n " , g .cfg .Name )
670
599
}
671
600
672
- func (g * pyGen ) genLeaksPreamble () {
673
- g .leakfile .Printf (patchLeaksPreamble , g .cfg .Name , g .cfg .Cmd )
674
- }
675
-
676
- func (g * pyGen ) genLeaksPostamble () {
677
- g .leakfile .Printf (patchLeaksPostamble )
678
- }
679
-
680
601
func (g * pyGen ) genPyBuildPreamble () {
681
602
g .pybuild .Printf (PyBuildPreamble , g .cfg .Name , g .cfg .Cmd )
682
603
}
0 commit comments