eval.h revision 11986:c12e4625ab56
113219Sodanrc@yahoo.com.br/*
213219Sodanrc@yahoo.com.br    pybind11/exec.h: Support for evaluating Python expressions and statements
313219Sodanrc@yahoo.com.br    from strings and files
413219Sodanrc@yahoo.com.br
513219Sodanrc@yahoo.com.br    Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
613219Sodanrc@yahoo.com.br                       Wenzel Jakob <wenzel.jakob@epfl.ch>
713219Sodanrc@yahoo.com.br
813219Sodanrc@yahoo.com.br    All rights reserved. Use of this source code is governed by a
913219Sodanrc@yahoo.com.br    BSD-style license that can be found in the LICENSE file.
1013219Sodanrc@yahoo.com.br*/
1113219Sodanrc@yahoo.com.br
1213219Sodanrc@yahoo.com.br#pragma once
1313219Sodanrc@yahoo.com.br
1413219Sodanrc@yahoo.com.br#pragma once
1513219Sodanrc@yahoo.com.br
1613219Sodanrc@yahoo.com.br#include "pybind11.h"
1713219Sodanrc@yahoo.com.br
1813219Sodanrc@yahoo.com.brNAMESPACE_BEGIN(pybind11)
1913219Sodanrc@yahoo.com.br
2013219Sodanrc@yahoo.com.brenum eval_mode {
2113219Sodanrc@yahoo.com.br    /// Evaluate a string containing an isolated expression
2213219Sodanrc@yahoo.com.br    eval_expr,
2313219Sodanrc@yahoo.com.br
2413219Sodanrc@yahoo.com.br    /// Evaluate a string containing a single statement. Returns \c none
2513219Sodanrc@yahoo.com.br    eval_single_statement,
2613219Sodanrc@yahoo.com.br
2713219Sodanrc@yahoo.com.br    /// Evaluate a string containing a sequence of statement. Returns \c none
2813219Sodanrc@yahoo.com.br    eval_statements
2913219Sodanrc@yahoo.com.br};
3013219Sodanrc@yahoo.com.br
3113219Sodanrc@yahoo.com.brtemplate <eval_mode mode = eval_expr>
3213219Sodanrc@yahoo.com.brobject eval(str expr, object global = object(), object local = object()) {
3313219Sodanrc@yahoo.com.br    if (!global) {
3413219Sodanrc@yahoo.com.br        global = reinterpret_borrow<object>(PyEval_GetGlobals());
3513219Sodanrc@yahoo.com.br        if (!global)
3613219Sodanrc@yahoo.com.br            global = dict();
3713219Sodanrc@yahoo.com.br    }
3813219Sodanrc@yahoo.com.br    if (!local)
3913219Sodanrc@yahoo.com.br        local = global;
4013219Sodanrc@yahoo.com.br
4113219Sodanrc@yahoo.com.br    /* PyRun_String does not accept a PyObject / encoding specifier,
4213219Sodanrc@yahoo.com.br       this seems to be the only alternative */
4313219Sodanrc@yahoo.com.br    std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr;
4413219Sodanrc@yahoo.com.br
4513219Sodanrc@yahoo.com.br    int start;
4613219Sodanrc@yahoo.com.br    switch (mode) {
4713219Sodanrc@yahoo.com.br        case eval_expr:             start = Py_eval_input;   break;
4813219Sodanrc@yahoo.com.br        case eval_single_statement: start = Py_single_input; break;
4913219Sodanrc@yahoo.com.br        case eval_statements:       start = Py_file_input;   break;
5013219Sodanrc@yahoo.com.br        default: pybind11_fail("invalid evaluation mode");
5113219Sodanrc@yahoo.com.br    }
5213219Sodanrc@yahoo.com.br
5313219Sodanrc@yahoo.com.br    PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
5413219Sodanrc@yahoo.com.br    if (!result)
5513219Sodanrc@yahoo.com.br        throw error_already_set();
5613219Sodanrc@yahoo.com.br    return reinterpret_steal<object>(result);
5713219Sodanrc@yahoo.com.br}
5813219Sodanrc@yahoo.com.br
5913219Sodanrc@yahoo.com.brtemplate <eval_mode mode = eval_statements>
6013219Sodanrc@yahoo.com.brobject eval_file(str fname, object global = object(), object local = object()) {
6113219Sodanrc@yahoo.com.br    if (!global) {
6213219Sodanrc@yahoo.com.br        global = reinterpret_borrow<object>(PyEval_GetGlobals());
6313219Sodanrc@yahoo.com.br        if (!global)
6413219Sodanrc@yahoo.com.br            global = dict();
6513219Sodanrc@yahoo.com.br    }
6613219Sodanrc@yahoo.com.br    if (!local)
6713219Sodanrc@yahoo.com.br        local = global;
6813219Sodanrc@yahoo.com.br
6913219Sodanrc@yahoo.com.br    int start;
7013219Sodanrc@yahoo.com.br    switch (mode) {
7113219Sodanrc@yahoo.com.br        case eval_expr:             start = Py_eval_input;   break;
7213219Sodanrc@yahoo.com.br        case eval_single_statement: start = Py_single_input; break;
7313219Sodanrc@yahoo.com.br        case eval_statements:       start = Py_file_input;   break;
7413219Sodanrc@yahoo.com.br        default: pybind11_fail("invalid evaluation mode");
7513219Sodanrc@yahoo.com.br    }
7613219Sodanrc@yahoo.com.br
7713219Sodanrc@yahoo.com.br    int closeFile = 1;
7813219Sodanrc@yahoo.com.br    std::string fname_str = (std::string) fname;
7913219Sodanrc@yahoo.com.br#if PY_VERSION_HEX >= 0x03040000
8013219Sodanrc@yahoo.com.br    FILE *f = _Py_fopen_obj(fname.ptr(), "r");
8113219Sodanrc@yahoo.com.br#elif PY_VERSION_HEX >= 0x03000000
8213219Sodanrc@yahoo.com.br    FILE *f = _Py_fopen(fname.ptr(), "r");
8313219Sodanrc@yahoo.com.br#else
8413219Sodanrc@yahoo.com.br    /* No unicode support in open() :( */
8513219Sodanrc@yahoo.com.br    auto fobj = reinterpret_steal<object>(PyFile_FromString(
8613219Sodanrc@yahoo.com.br        const_cast<char *>(fname_str.c_str()),
8713219Sodanrc@yahoo.com.br        const_cast<char*>("r")));
8813219Sodanrc@yahoo.com.br    FILE *f = nullptr;
8913219Sodanrc@yahoo.com.br    if (fobj)
9013219Sodanrc@yahoo.com.br        f = PyFile_AsFile(fobj.ptr());
9113219Sodanrc@yahoo.com.br    closeFile = 0;
9213219Sodanrc@yahoo.com.br#endif
9313219Sodanrc@yahoo.com.br    if (!f) {
9413219Sodanrc@yahoo.com.br        PyErr_Clear();
9513219Sodanrc@yahoo.com.br        pybind11_fail("File \"" + fname_str + "\" could not be opened!");
9613219Sodanrc@yahoo.com.br    }
9713219Sodanrc@yahoo.com.br
9813219Sodanrc@yahoo.com.br    PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
9913219Sodanrc@yahoo.com.br                                    local.ptr(), closeFile);
10013219Sodanrc@yahoo.com.br    if (!result)
10113219Sodanrc@yahoo.com.br        throw error_already_set();
10213219Sodanrc@yahoo.com.br    return reinterpret_steal<object>(result);
10313219Sodanrc@yahoo.com.br}
10413219Sodanrc@yahoo.com.br
10513219Sodanrc@yahoo.com.brNAMESPACE_END(pybind11)
10613219Sodanrc@yahoo.com.br