Loading...
Searching...
No Matches
bbm_python_interpreter.h
Go to the documentation of this file.
1#ifndef _BBM_PYTHON_INTERPRETER_H_
2#define _BBM_PYTHON_INTERPRETER_H_
3
4#ifndef BBM_PYTHON
5 #error Fatal Error: Python Support not enabled for BBM (-DBBM_PYTHON=ON)
6#endif /* BBM_PYTHON */
7
8#include <cassert>
9
10#include <pybind11/embed.h>
11namespace py = pybind11;
12
13#include "util/macro_util.h"
14#include "io/dynamic_library.h"
15
16/***********************************************************************/
17/*! \file bbm_python_interpreter.h
18 \brief Python interpreter for BBM modules
19************************************************************************/
20
21namespace bbm {
22 namespace python {
23
24 /*******************************************************************/
25 /*! \brief Python interpreter with BBM module imported.
26
27 \tparam CONF = configuration of the BBM environment to use
28 ********************************************************************/
29 template<typename CONF> requires concepts::config<CONF>
31 {
32 //! \brief Constructor: initializes BBM python interface.
34 {
35 // ensure the python dynamic library is loaded
36 _python = loadDynamicLibrary( BBM_STRINGIFY(BBM_PYTHON_LIBRARY) );
37 assert(_python);
38
39 // setup python
40 py::initialize_interpreter();
41 _scope = py::module::import("__main__").attr("__dict__");
42
43 // import bbm
44 std::string import_string = std::string("from ") + std::string(BBM_STRINGIFY(BBM_NAME)) + std::string("_") + std::string(get_config<CONF>::name) + std::string(" import *");
45 py::exec(import_string, _scope);
46 }
47
48 //! \brief Destructor releases scope and python interpreter appropriately
50 {
51 _scope.release();
52 py::finalize_interpreter();
54 }
55
56 /******************************************************************/
57 /*! \brief Execute Python code within the BBM environment.
58
59 \tparam RET_TYPE = type of the return type (need explicit casting)
60 \param prog = string of python code to execute.
61 \returns object of type RET_TYPE
62
63 Usage Example:
64 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
65 interpreter ii
66 auto ptr = i.capture<BsdfPtr>("Lambertian()");
67 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68 Returns a BsdfPtr objects to a Lambertian bsdf.
69 *******************************************************************/
70 template<typename RET_TYPE>
71 RET_TYPE capture(const std::string& prog) const
72 {
73 try {
74 return py::eval(prog, _scope).cast<RET_TYPE>();
75 } catch(...) { throw std::runtime_error("BBM: python expression \"" + prog + "\" did not return a valid BBM Bsdf."); }
76 }
77
78 /******************************************************************/
79 /*! \brief Execute Python code within the BBM environment.
80
81 \param prog = string of python code to execute.
82
83 Usage Example:
84 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
85 interpreter i;
86 i.execute<floatRGB>("print(str(Lambertian()))");
87 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
88 Prints the default Lambertian bsdf.
89
90 *******************************************************************/
91 void execute(const std::string& prog) const
92 {
93 try {
94 py::eval(prog, _scope);
95 } catch(...) { throw std::runtime_error("BBM: failed to execute python expression \"" + prog + "\""); }
96 }
97
98 private:
100 py::object _scope;
101 };
102
103
104 /*******************************************************************/
105 /*! \brief Helper function to execute a python string and capture the output
106
107 \tparam RET_TYPE = type of the return value (must be specified manually)
108 \tparam CONF = config of the bbm python lib.
109 \param prog = string of python program to run
110 ********************************************************************/
111 template<typename RET_TYPE, typename CONF=get_config<RET_TYPE>> requires concepts::config<CONF>
112 RET_TYPE capture(const std::string& prog)
113 {
115 return intp.template capture<RET_TYPE>(prog);
116 }
117
118 /*******************************************************************/
119 /*! \brief Helper function to execute a python string and ignore the output
120
121 \tparam CONF = config of the bbm python lib
122 \param prog = string of python program to run
123 ******************************************************************/
124 template<typename CONF> requires concepts::config<CONF>
125 void execute(const std::string& prog)
126 {
128 intp.execute(prog);
129 }
130
131 } // end python namespace
132} // end bbm namespace
133
134#endif /* _BBM_PYTHON_INTERPRETER_H_ */
135
config concept
Definition: config.h:31
load and unload a dynamic library
General macro utilities.
#define BBM_STRINGIFY(...)
Expand VA_ARGS before converting to a string of comma separated elements.
Definition: macro_util.h:74
void execute(const std::string &prog)
Helper function to execute a python string and ignore the output.
Definition: bbm_python_interpreter.h:125
RET_TYPE capture(const std::string &prog)
Helper function to execute a python string and capture the output.
Definition: bbm_python_interpreter.h:112
Definition: aggregatebsdf.h:29
typename std::decay_t< T >::Config get_config
get_config type trait
Definition: config.h:49
dl_handle_t loadDynamicLibrary(const std::string &name)
Definition: dynamic_library.h:37
void * dl_handle_t
Definition: dynamic_library.h:35
void closeDynamicLibrary(dl_handle_t handle)
Definition: dynamic_library.h:42
Python interpreter with BBM module imported.
Definition: bbm_python_interpreter.h:31
RET_TYPE capture(const std::string &prog) const
Execute Python code within the BBM environment.
Definition: bbm_python_interpreter.h:71
~interpreter(void)
Destructor releases scope and python interpreter appropriately.
Definition: bbm_python_interpreter.h:49
py::object _scope
Definition: bbm_python_interpreter.h:100
dl_handle_t _python
Definition: bbm_python_interpreter.h:99
void execute(const std::string &prog) const
Execute Python code within the BBM environment.
Definition: bbm_python_interpreter.h:91
interpreter(void)
Constructor: initializes BBM python interface.
Definition: bbm_python_interpreter.h:33