[pypy-dev] pypy callback function pointer become invalid

Yicong Huang hengha.mao at gmail.com
Mon Aug 17 12:59:52 CEST 2015


Hi Armin,

Great thanks for the demo code!
I think the approach should work, but there might be a lot of work to do in
"run_function" to perform a simple python function call.
Assuming we would like to do the simple work as original
pypy_execute_source_ptr()
does, with such approch, we need to pass python code as char* to callback
function "def run_function(p_src)".
In theory we could do everything, even much more complex than eval().
However, to perform the python function call, we need to parse char*(python
code), a python code lexer, praser, JIT and etc, in other words do all the
work that  pypy_execute_source() did. The only difference is we don't need
pypy_execute_source_ptr(), but pypy_execute_source().

I think pypy_execute_source() plays the same role as eval() in your example
code.
So why don't PyPy expose and API to do such job ? ( pypy_execute_source(),
either python or C)

On Mon, Aug 17, 2015 at 4:08 PM, Armin Rigo <arigo at tunes.org> wrote:

> Hi Yicong,
>
> On 17 August 2015 at 08:40, Yicong Huang <hengha.mao at gmail.com> wrote:
> > yes, we could use a structure to wrap severl python callback function
> > pointers in one execution.
> > However, the issue is that we might not be able to get all python
> functions
> > that would be executed at the beginning.
>
> The basic idea is to define whatever API you need with just one call
> to pypy_execute_source_ptr().  If you want to be able to compile and
> execute arbitrary Python functions, just make that feature available
> in your API.  This is the same idea as PyRun_SimpleString(), which is
> *one* API function but lets you execute arbitrary Python code.
> Example:
>
>
> struct API {
>     long (*run_function)(char *);
> };
> struct API api;   /* global var */
>
> int initialize_api(void) {    /* run this only once */
>     static char source[] =
>         "import sys; sys.path.insert(0, '.'); "
>         "import interface; interface.fill_api(c_argument)";
>     pypy_execute_source_ptr(source, &api);
> }
>
> /* then execute 'api.run_function(some_source_code)' any number of times */
>
>
> # file "interface.py"
>
> import cffi
>
> ffi = cffi.FFI()
> ffi.cdef('''
> struct API {
>     long (*run_function)(char *);
> };
> ''')
>
> @ffi.callback("long(char *)")
> def run_function(p_src):
>     src = ffi.string(p_src)
>     # here 'src' is a string, we can do whatever we want with it---like
> eval()
>     return eval(src, {})
>
> def fill_api(ptr):
>     global api
>     api = ffi.cast("struct API*", ptr)
>     api.run_function = run_function
>
>
> ---
> Armin
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/pypy-dev/attachments/20150817/d73e04e1/attachment.html>


More information about the pypy-dev mailing list