@@ -40,7 +40,7 @@ from cpython.object cimport PyObject_Call
40
40
from cpython.ref cimport Py_INCREF
41
41
42
42
from .paridecl cimport *
43
- from .stack cimport new_gen, clone_gen_noclear, DetachGen
43
+ from .stack cimport new_gen, new_gen_noclear, clone_gen_noclear, DetachGen
44
44
from .gen cimport objtogen
45
45
46
46
try :
@@ -57,9 +57,12 @@ cdef inline GEN call_python_func_impl "call_python_func"(GEN* args, object py_fu
57
57
The arguments are converted from ``GEN`` to a cypari ``gen`` before
58
58
calling ``py_func``. The result is converted back to a PARI ``GEN``.
59
59
"""
60
+ # We need to ensure that nothing above avma is touched
61
+ avmaguard = new_gen_noclear(< GEN> avma)
62
+
60
63
# How many arguments are there?
61
64
cdef Py_ssize_t n = 0
62
- while args[n] ! = NULL :
65
+ while args[n] is not NULL :
63
66
n += 1
64
67
65
68
# Construct a Python tuple for args
@@ -78,9 +81,16 @@ cdef inline GEN call_python_func_impl "call_python_func"(GEN* args, object py_fu
78
81
if r is None :
79
82
return gnil
80
83
84
+ # Safely delete r and avmaguard
81
85
d = DetachGen(objtogen(r))
82
86
del r
83
- return d.detach()
87
+ res = d.detach()
88
+ d = DetachGen(avmaguard)
89
+ del avmaguard
90
+ d.detach()
91
+
92
+ return res
93
+
84
94
85
95
# We rename this function to be able to call it with a different
86
96
# signature. In particular, we want manual exception handling and we
@@ -166,6 +176,21 @@ cpdef Gen objtoclosure(f):
166
176
>>> objtoclosure(printme)('matid(2)')
167
177
[1, 0; 0, 1]
168
178
179
+ Construct the Riemann zeta function using a closure:
180
+
181
+ >>> from cypari2 import Pari; pari = Pari()
182
+ >>> def coeffs(n):
183
+ ... return [1 for i in range(n)]
184
+ >>> Z = pari.lfuncreate([coeffs, 0, [0], 1, 1, 1, 1])
185
+ >>> Z.lfun(2)
186
+ 1.64493406684823
187
+
188
+ A trivial closure:
189
+
190
+ >>> f = pari(lambda x: x)
191
+ >>> f(10)
192
+ 10
193
+
169
194
Test various kinds of errors:
170
195
171
196
>>> mul(4)
0 commit comments