From b2f53e1acfe08829de63637c2adc13ccfa5fe034 Mon Sep 17 00:00:00 2001 From: John Zwinck Date: Fri, 21 Oct 2016 15:55:06 +0800 Subject: [PATCH] exec/eval(): add overloads for char const* Many times the caller may have a string created in C++, so there is no need to wrap it in a Python object when the only thing done with the object is extract. --- doc/tutorial.qbk | 2 ++ include/boost/python/exec.hpp | 16 ++++++++++ src/exec.cpp | 56 ++++++++++++++++++++++++----------- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 74126476..a1f7fc24 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -1417,6 +1417,8 @@ eval evaluates the given expression and returns the resulting value. exec executes the given code (typically a set of statements) returning the result, and exec_file executes the code contained in the given file. +There are also overloads taking `char const*` instead of str as the first argument. + The [^globals] and [^locals] parameters are Python dictionaries containing the globals and locals of the context in which to run the code. For most intents and purposes you can use the namespace dictionary of the diff --git a/include/boost/python/exec.hpp b/include/boost/python/exec.hpp index 3ed1e15c..32a74991 100644 --- a/include/boost/python/exec.hpp +++ b/include/boost/python/exec.hpp @@ -20,6 +20,10 @@ object BOOST_PYTHON_DECL eval(str string, object global = object(), object local = object()); +object +BOOST_PYTHON_DECL +eval(char const *string, object global = object(), object local = object()); + // Execute an individual python statement from str. // global and local are the global and local scopes respectively, // used during execution. @@ -27,6 +31,10 @@ object BOOST_PYTHON_DECL exec_statement(str string, object global = object(), object local = object()); +object +BOOST_PYTHON_DECL +exec_statement(char const *string, object global = object(), object local = object()); + // Execute python source code from str. // global and local are the global and local scopes respectively, // used during execution. @@ -34,6 +42,10 @@ object BOOST_PYTHON_DECL exec(str string, object global = object(), object local = object()); +object +BOOST_PYTHON_DECL +exec(char const *string, object global = object(), object local = object()); + // Execute python source code from file filename. // global and local are the global and local scopes respectively, // used during execution. @@ -41,6 +53,10 @@ object BOOST_PYTHON_DECL exec_file(str filename, object global = object(), object local = object()); +object +BOOST_PYTHON_DECL +exec_file(char const *filename, object global = object(), object local = object()); + } } diff --git a/src/exec.cpp b/src/exec.cpp index fa2860e4..603a6f01 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -15,6 +15,11 @@ namespace python { object BOOST_PYTHON_DECL eval(str string, object global, object local) +{ + return eval(python::extract(string)); +} + +object BOOST_PYTHON_DECL eval(char const *string, object global, object local) { // Set suitable default values for global and local dicts. if (global.is_none()) @@ -26,7 +31,7 @@ object BOOST_PYTHON_DECL eval(str string, object global, object local) } if (local.is_none()) local = global; // should be 'char const *' but older python versions don't use 'const' yet. - char *s = python::extract(string); + char *s = const_cast(string); PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr()); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); @@ -34,23 +39,10 @@ object BOOST_PYTHON_DECL eval(str string, object global, object local) object BOOST_PYTHON_DECL exec(str string, object global, object local) { - // Set suitable default values for global and local dicts. - if (global.is_none()) - { - if (PyObject *g = PyEval_GetGlobals()) - global = object(detail::borrowed_reference(g)); - else - global = dict(); - } - if (local.is_none()) local = global; - // should be 'char const *' but older python versions don't use 'const' yet. - char *s = python::extract(string); - PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); - if (!result) throw_error_already_set(); - return object(detail::new_reference(result)); + return exec(python::extract(string)); } -object BOOST_PYTHON_DECL exec_statement(str string, object global, object local) +object BOOST_PYTHON_DECL exec(char const *string, object global, object local) { // Set suitable default values for global and local dicts. if (global.is_none()) @@ -62,7 +54,30 @@ object BOOST_PYTHON_DECL exec_statement(str string, object global, object local) } if (local.is_none()) local = global; // should be 'char const *' but older python versions don't use 'const' yet. - char *s = python::extract(string); + char *s = const_cast(string); + PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); + if (!result) throw_error_already_set(); + return object(detail::new_reference(result)); +} + +object BOOST_PYTHON_DECL exec_statement(str string, object global, object local) +{ + return exec_statement(python::extract(string), global, local); +} + +object BOOST_PYTHON_DECL exec_statement(char const *string, object global, object local) +{ + // Set suitable default values for global and local dicts. + if (global.is_none()) + { + if (PyObject *g = PyEval_GetGlobals()) + global = object(detail::borrowed_reference(g)); + else + global = dict(); + } + if (local.is_none()) local = global; + // should be 'char const *' but older python versions don't use 'const' yet. + char *s = const_cast(string); PyObject* result = PyRun_String(s, Py_single_input, global.ptr(), local.ptr()); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); @@ -72,6 +87,11 @@ object BOOST_PYTHON_DECL exec_statement(str string, object global, object local) // global and local are the global and local scopes respectively, // used during execution. object BOOST_PYTHON_DECL exec_file(str filename, object global, object local) +{ + return exec_file(python::extract(filename), global, local); +} + +object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object local) { // Set suitable default values for global and local dicts. if (global.is_none()) @@ -83,7 +103,7 @@ object BOOST_PYTHON_DECL exec_file(str filename, object global, object local) } if (local.is_none()) local = global; // should be 'char const *' but older python versions don't use 'const' yet. - char *f = python::extract(filename); + char *f = const_cast(filename); // Let python open the file to avoid potential binary incompatibilities. #if PY_VERSION_HEX >= 0x03040000 FILE *fs = _Py_fopen(f, "r");