From 464c43513ed08048a728274e97615ad55c26a348 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 8 Jul 2016 15:06:25 +0200 Subject: [PATCH] further eval() improvements --- .appveyor.yml | 3 --- include/pybind11/eval.h | 35 +++++++++++++++++++++++++++-------- include/pybind11/pytypes.h | 5 +++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index de0adb12..617a197d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -23,7 +23,4 @@ build_script: - cd c:\projects\pybind11 - cmake -G "%CMAKE_PLATFORM%" -DPYTHON_EXECUTABLE:FILEPATH=%PYTHON_DIR%/python.exe - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - - cmake --build . --config %Configuration% -- /v:m /logger:%MSBuildLogger% - - set PATH=%PYTHON_DIR%;%PATH% - - python example/example18.py - cmake --build . --config %Configuration% --target check -- /v:m /logger:%MSBuildLogger% diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h index becf882e..4dfb1972 100644 --- a/include/pybind11/eval.h +++ b/include/pybind11/eval.h @@ -29,7 +29,7 @@ enum eval_mode { }; template -object eval(const std::string& str, object global = object(), object local = object()) { +object eval(str expr, object global = object(), object local = object()) { if (!global) { global = object(PyEval_GetGlobals(), true); if (!global) @@ -38,6 +38,10 @@ object eval(const std::string& str, object global = object(), object local = obj if (!local) local = global; + /* PyRun_String does not accept a PyObject / encoding specifier, + this seems to be the only alternative */ + std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr; + int start; switch (mode) { case eval_expr: start = Py_eval_input; break; @@ -46,7 +50,7 @@ object eval(const std::string& str, object global = object(), object local = obj default: pybind11_fail("invalid evaluation mode"); } - object result(PyRun_String(str.c_str(), start, global.ptr(), local.ptr()), false); + object result(PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()), false); if (!result) throw error_already_set(); @@ -54,7 +58,7 @@ object eval(const std::string& str, object global = object(), object local = obj } template -object eval_file(const std::string& fname, object global = object(), object local = object()) { +object eval_file(str fname, object global = object(), object local = object()) { if (!global) { global = object(PyEval_GetGlobals(), true); if (!global) @@ -71,12 +75,27 @@ object eval_file(const std::string& fname, object global = object(), object loca default: pybind11_fail("invalid evaluation mode"); } - FILE *f = fopen(fname.c_str(), "r"); - if (!f) - pybind11_fail("File \"" + fname + "\" could not be opened!"); + int closeFile = 1; + std::string fname_str = (std::string) fname; +#if PY_VERSION_HEX >= 0x03040000 + FILE *f = _Py_fopen_obj(fname.ptr(), "r"); +#elif PY_VERSION_HEX >= 0x03000000 + FILE *f = _Py_fopen(fname.ptr(), "r"); +#else + /* No unicode support in open() :( */ + object fobj(PyFile_FromString(fname_str.c_str(), const_cast("r")), false); + FILE *f = nullptr; + if (fobj) + f = PyFile_AsFile(fobj.ptr()); + closeFile = 0; +#endif + if (!f) { + PyErr_Clear(); + pybind11_fail("File \"" + fname_str + "\" could not be opened!"); + } - object result(PyRun_FileEx(f, fname.c_str(), Py_file_input, global.ptr(), - local.ptr(), 1), + object result(PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), + local.ptr(), closeFile), false); if (!result) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 6eee186d..d0248079 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -343,6 +343,11 @@ public: if (!m_ptr) pybind11_fail("Could not allocate string object!"); } + str(const char *c) + : object(PyUnicode_FromString(c), false) { + if (!m_ptr) pybind11_fail("Could not allocate string object!"); + } + operator std::string() const { object temp = *this; if (PyUnicode_Check(m_ptr)) {