Skip to content

Commit 034e882

Browse files
committed
Pybind11 compatibility
* Add some compatibility structures to a separate header file * Integrate scope handling to match pybind11 API * register_enum and register_g3module functions
1 parent d8feb0e commit 034e882

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+472
-371
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ set(Boost_USE_STATIC_LIBS OFF)
5252
set(Boost_USE_MULTITHREADED ON)
5353
set(Boost_USE_STATIC_RUNTIME OFF)
5454
set(Boost_PYTHON_VERSION ${Python_VERSION})
55-
find_package(Boost COMPONENTS python REQUIRED)
55+
find_package(Boost CONFIG COMPONENTS python REQUIRED)
5656

5757
# Interface library for flags and library dependencies
5858
add_library(spt3g INTERFACE)

calibration/src/BoloProperties.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ std::string BolometerProperties::Description() const
5757
G3_SERIALIZABLE_CODE(BolometerProperties);
5858
G3_SERIALIZABLE_CODE(BolometerPropertiesMap);
5959

60-
PYBINDINGS("calibration") {
60+
PYBINDINGS("calibration", scope) {
6161
EXPORT_FRAMEOBJECT(BolometerProperties, py::init<>(),
6262
"Physical bolometer properties, such as detector angular offsets. "
6363
"Does not include tuning-dependent properties of the detectors.")
@@ -89,7 +89,7 @@ PYBINDINGS("calibration") {
8989
"Name of the pixel type of which this detector is a part")
9090
;
9191

92-
py::enum_<BolometerProperties::CouplingType>("BolometerCouplingType",
92+
register_enum<BolometerProperties::CouplingType>(scope, "BolometerCouplingType",
9393
"Coupling type for BolometerProperties objects.")
9494
.value("Unknown", BolometerProperties::Unknown)
9595
.value("Optical", BolometerProperties::Optical)

calibration/src/PointingProperties.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ std::string PointingProperties::Description() const
2626
G3_SERIALIZABLE_CODE(PointingProperties);
2727
G3_SERIALIZABLE_CODE(PointingPropertiesMap);
2828

29-
PYBINDINGS("calibration") {
29+
PYBINDINGS("calibration", scope) {
3030
EXPORT_FRAMEOBJECT(PointingProperties, py::init<>(),
3131
"Pointing model parameters to be used for offline pointing corrections.")
3232
.def_readwrite("tiltLat", &PointingProperties::tiltLat,

calibration/src/python.cxx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
#include <pybindings.h>
22

3-
SPT3G_PYTHON_MODULE(calibration)
3+
SPT3G_PYTHON_MODULE(calibration, scope)
44
{
55
// Python bindings dependencies
6-
py::import("spt3g.core");
7-
8-
// Disable noise in doc strings
9-
py::docstring_options docopts(true, true, false);
10-
11-
// Python bindings for this module
12-
G3ModuleRegistrator::CallRegistrarsFor("calibration");
6+
scope.import("spt3g.core");
137
}
148

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#pragma once
2+
3+
#include <boost/python.hpp>
4+
#include <string>
5+
6+
#include <G3Logging.h>
7+
8+
namespace py = boost::python;
9+
10+
// Python runtime context to simplify acquiring or releasing the GIL as necessary.
11+
// To use, simply construct the context object where necessary, e.g.
12+
// G3PythonContext ctx("mycontext", false);
13+
// The context destructor will clean up after itself (releasing the GIL if acquired, and
14+
// vice versa). If hold_gil is true, the context will ensure the GIL is held at construction,
15+
// and released at destruction. If hold_gil is false, the context will save the current thread
16+
// state and release the GIL at construction, and re-acquire it at destruction.
17+
class G3PythonContext {
18+
public:
19+
G3PythonContext(std::string name, bool hold_gil=false);
20+
~G3PythonContext();
21+
22+
private:
23+
std::string name_;
24+
bool hold_;
25+
PyGILState_STATE gil_;
26+
PyThreadState *thread_;
27+
28+
SET_LOGGER("G3PythonContext");
29+
};
30+
31+
// Convenience class for initializing and finalizing the Python interpreter. This class
32+
// will initialize the python interpeter at construction (e.g. at the beginning of a C++
33+
// compiled program), and immediately initialize the appropriate G3PythonContext depending
34+
// on the value of hold_gil. At destruction, it will exit the python context and finalize
35+
// the interpreter. The python interpreter should be initialized only once, typically at
36+
// the beginning of the main program.
37+
class G3PythonInterpreter {
38+
public:
39+
G3PythonInterpreter();
40+
~G3PythonInterpreter();
41+
42+
private:
43+
bool init_;
44+
45+
SET_LOGGER("G3PythonInterpreter");
46+
};
47+
48+
// pybind11 compatibility functions
49+
namespace boost { namespace python {
50+
51+
class module_ : public scope
52+
{
53+
public:
54+
static auto import(const std::string &name) {
55+
return py::import(name.c_str());
56+
}
57+
58+
py::object def_submodule(const std::string &name);
59+
60+
template <typename...Args>
61+
static auto def(Args&&... args) {
62+
return py::def(std::forward<Args>(args)...);
63+
}
64+
};
65+
66+
class gil_scoped_release : public G3PythonContext
67+
{
68+
public:
69+
gil_scoped_release() : G3PythonContext("release", false) {};
70+
};
71+
72+
class gil_scoped_acquire : public G3PythonContext
73+
{
74+
public:
75+
gil_scoped_acquire() : G3PythonContext("acquire", true) {};
76+
};
77+
78+
class scoped_interpreter : public G3PythonInterpreter {};
79+
80+
template <typename T>
81+
T cast(const py::object &obj)
82+
{
83+
return py::extract<T>(obj)();
84+
}
85+
86+
template <typename T>
87+
bool isinstance(const py::object &obj)
88+
{
89+
return py::extract<T>(obj).check();
90+
}
91+
92+
class value_error : std::exception
93+
{
94+
public:
95+
std::string msg;
96+
value_error(std::string msg="") : msg(msg) {};
97+
const char * what() const throw() { return msg.c_str(); }
98+
};
99+
100+
class index_error : std::exception
101+
{
102+
public:
103+
std::string msg;
104+
index_error(std::string msg="") : msg(msg) {};
105+
const char * what() const throw() { return msg.c_str(); }
106+
};
107+
108+
class type_error : std::exception
109+
{
110+
public:
111+
std::string msg;
112+
type_error(std::string msg="") : msg(msg) {};
113+
const char * what() const throw() { return msg.c_str(); }
114+
};
115+
116+
class key_error : std::exception
117+
{
118+
public:
119+
std::string msg;
120+
key_error(std::string msg="") : msg(msg) {};
121+
const char * what() const throw() { return msg.c_str(); }
122+
};
123+
124+
class buffer_error : std::exception
125+
{
126+
public:
127+
std::string msg;
128+
buffer_error(std::string msg="") : msg(msg) {};
129+
const char * what() const throw() { return msg.c_str(); }
130+
};
131+
132+
}}

0 commit comments

Comments
 (0)