mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-31 23:30:30 +00:00
1d1f81b278
This commit includes modifications that are needed to get pybind11 to work with PyPy. The full test suite compiles and runs except for a last few functions that are commented out (due to problems in PyPy that were reported on the PyPy bugtracker). Two somewhat intrusive changes were needed to make it possible: two new tags ``py::buffer_protocol()`` and ``py::metaclass()`` must now be specified to the ``class_`` constructor if the class uses the buffer protocol and/or requires a metaclass (e.g. for static properties). Note that this is only for the PyPy version based on Python 2.7 for now. When the PyPy 3.x has caught up in terms of cpyext compliance, a PyPy 3.x patch will follow.
113 lines
3.4 KiB
C++
113 lines
3.4 KiB
C++
/*
|
|
pybind11/exec.h: Support for evaluating Python expressions and statements
|
|
from strings and files
|
|
|
|
Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
|
|
Wenzel Jakob <wenzel.jakob@epfl.ch>
|
|
|
|
All rights reserved. Use of this source code is governed by a
|
|
BSD-style license that can be found in the LICENSE file.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#pragma once
|
|
|
|
#include "pybind11.h"
|
|
|
|
NAMESPACE_BEGIN(pybind11)
|
|
|
|
enum eval_mode {
|
|
/// Evaluate a string containing an isolated expression
|
|
eval_expr,
|
|
|
|
/// Evaluate a string containing a single statement. Returns \c none
|
|
eval_single_statement,
|
|
|
|
/// Evaluate a string containing a sequence of statement. Returns \c none
|
|
eval_statements
|
|
};
|
|
|
|
template <eval_mode mode = eval_expr>
|
|
object eval(str expr, object global = object(), object local = object()) {
|
|
if (!global) {
|
|
global = reinterpret_borrow<object>(PyEval_GetGlobals());
|
|
if (!global)
|
|
global = dict();
|
|
}
|
|
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;
|
|
case eval_single_statement: start = Py_single_input; break;
|
|
case eval_statements: start = Py_file_input; break;
|
|
default: pybind11_fail("invalid evaluation mode");
|
|
}
|
|
|
|
PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
|
|
if (!result)
|
|
throw error_already_set();
|
|
return reinterpret_steal<object>(result);
|
|
}
|
|
|
|
template <eval_mode mode = eval_statements>
|
|
object eval_file(str fname, object global = object(), object local = object()) {
|
|
if (!global) {
|
|
global = reinterpret_borrow<object>(PyEval_GetGlobals());
|
|
if (!global)
|
|
global = dict();
|
|
}
|
|
if (!local)
|
|
local = global;
|
|
|
|
int start;
|
|
switch (mode) {
|
|
case eval_expr: start = Py_eval_input; break;
|
|
case eval_single_statement: start = Py_single_input; break;
|
|
case eval_statements: start = Py_file_input; break;
|
|
default: pybind11_fail("invalid evaluation mode");
|
|
}
|
|
|
|
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() :( */
|
|
auto fobj = reinterpret_steal<object>(PyFile_FromString(
|
|
const_cast<char *>(fname_str.c_str()),
|
|
const_cast<char*>("r")));
|
|
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!");
|
|
}
|
|
|
|
#if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION)
|
|
PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(),
|
|
local.ptr());
|
|
(void) closeFile;
|
|
#else
|
|
PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
|
|
local.ptr(), closeFile);
|
|
#endif
|
|
|
|
if (!result)
|
|
throw error_already_set();
|
|
return reinterpret_steal<object>(result);
|
|
}
|
|
|
|
NAMESPACE_END(pybind11)
|