8000 Convert internal utilities to pybind11 · matplotlib/matplotlib@f33f6cf · GitHub
[go: up one dir, main page]

Skip to content
Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f33f6cf

Browse files
committed
Convert internal utilities to pybind11
1 parent 24518d6 commit f33f6cf

File tree

2 files changed

+88
-89
lines changed

2 files changed

+88
-89
lines changed

src/_c_internal_utils.cpp

Lines changed: 87 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
1+
#include <stdexcept>
2+
13
#ifdef _WIN32
24
#define WIN32_LEAN_AND_MEAN
35
// Windows 10, for latest HiDPI API support.
46
#define WINVER 0x0A00
57
#define _WIN32_WINNT 0x0A00
68
#endif
7-
#define PY_SSIZE_T_CLEAN
8-
#include <Python.h>
9+
#include <pybind11/pybind11.h>
910
#ifdef __linux__
1011
#include <dlfcn.h>
1112
#endif
1213
#ifdef _WIN32
1314
#include <Objbase.h>
1415
#include <Shobjidl.h>
1516
#include <Windows.h>
17+
#define UNUSED_ON_NON_WINDOWS(x) x
18+
#else
19+
#define UNUSED_ON_NON_WINDOWS Py_UNUSED
1620
#endif
1721

18-
static PyObject*
19-
mpl_display_is_valid(PyObject* module)
22+
namespace py = pybind11;
23+
using namespace pybind11::literals;
24+
25+
static bool
26+
mpl_display_is_valid(void)
2027
{
2128
#ifdef __linux__
2229
void* libX11;
@@ -34,11 +41,10 @@ mpl_display_is_valid(PyObject* module)
3441
XCloseDisplay(display);
3542
}
3643
if (dlclose(libX11)) {
37-
PyErr_SetString(PyExc_RuntimeError, dlerror());
38-
return NULL;
44+
throw std::runtime_error(dlerror());
3945
}
4046
if (display) {
41-
Py_RETURN_TRUE;
47+
return true;
4248
}
4349
}
4450
void* libwayland_client;
@@ -56,84 +62,74 @@ mpl_display_is_valid(PyObject* module)
5662
wl_display_disconnect(display);
5763
}
5864
if (dlclose(libwayland_client)) {
59-
PyErr_SetString(PyExc_RuntimeError, dlerror());
60-
return NULL;
65+
throw std::runtime_error(dlerror());
6166
}
6267
if (display) {
63-
Py_RETURN_TRUE;
68+
return true;
6469
}
6570
}
66-
Py_RETURN_FALSE;
71+
return false;
6772
#else
68-
Py_RETURN_TRUE;
73+
return true;
6974
#endif
7075
}
7176

72-
static PyObject*
73-
mpl_GetCurrentProcessExplicitAppUserModelID(PyObject* module)
77+
static py::object
78+
mpl_GetCurrentProcessExplicitAppUserModelID(void)
7479
{
7580
#ifdef _WIN32
7681
wchar_t* appid = NULL;
7782
HRESULT hr = GetCurrentProcessExplicitAppUserModelID(&appid);
7883
if (FAILED(hr)) {
79-
return PyErr_SetFromWindowsErr(hr);
84+
PyErr_SetFromWindowsErr(hr);
85+
throw py::error_already_set();
8086
}
81-
PyObject* py_appid = PyUnicode_FromWideChar(appid, -1);
87+
auto py_appid = py::cast(appid);
8288
CoTaskMemFree(appid);
8389
return py_appid;
8490
#else
85-
Py_RETURN_NONE;
91+
return py::none();
8692
#endif
8793
}
8894

89-
static PyObject*
90-
mpl_SetCurrentProcessExplicitAppUserModelID(PyObject* module, PyObject* arg)
95+
static void
96+
mpl_SetCurrentProcessExplicitAppUserModelID(const wchar_t* UNUSED_ON_NON_WINDOWS(appid))
9197
{
9298
#ifdef _WIN32
93-
wchar_t* appid = PyUnicode_AsWideCharString(arg, NULL);
94-
if (!appid) {
95-
return NULL;
96-
}
9799
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(appid);
98-
PyMem_Free(appid);
99100
if (FAILED(hr)) {
100-
return PyErr_SetFromWindowsErr(hr);
101+
PyErr_SetFromWindowsErr(hr);
102+
throw py::error_already_set();
101103
}
102-
Py_RETURN_NONE;
103-
#else
104-
Py_RETURN_NONE;
105104
#endif
106105
}
107106

108-
static PyObject*
109-
mpl_GetForegroundWindow(PyObject* module)
107+
static py::object
108+
mpl_GetForegroundWindow(void)
110109
{
111110
#ifdef _WIN32
112-
return PyLong_FromVoidPtr(GetForegroundWindow());
111+
return py::capsule(GetForegroundWindow(), "HWND");
113112
#else
114-
Py_RETURN_NONE;
113+
return py::none();
115114
#endif
116115
}
117116

118-
static PyObject*
119-
mpl_SetForegroundWindow(PyObject* module, PyObject *arg)
117+
static void
118+
mpl_SetForegroundWindow(py::capsule UNUSED_ON_NON_WINDOWS(handle_p))
120119
{
121120
#ifdef _WIN32
122-
HWND handle = PyLong_AsVoidPtr(arg);
123-
if (PyErr_Occurred()) {
124-
return NULL;
125-
}
126-
if (!SetForegroundWindow(handle)) {
127-
return PyErr_Format(PyExc_RuntimeError, "Error setting window");
128-
}
129-
Py_RETURN_NONE;
130-
#else
131-
Py_RETURN_NONE;
121+
if (handle_p.name() != "HWND") {
122+
throw std::runtime_error("Handle must be a value returned from Win32_GetForegroundWindow");
123+
}
124+
HWND handle = static_cast<HWND>(handle_p.get_pointer());
125+
if (!SetForegroundWindow(handle)) {
126+
throw std::runtime_error("Error setting window");
127+
}
132128
#endif
133129
}
134130

135-
static PyObject*
136-
mpl_SetProcessDpiAwareness_max(PyObject* module)
131+
static void
132+
mpl_SetProcessDpiAwareness_max(void)
137133
{
138134
#ifdef _WIN32
139135
#ifdef _DPI_AWARENESS_CONTEXTS_
@@ -171,49 +167,52 @@ mpl_SetProcessDpiAwareness_max(PyObject* module)
171167
SetProcessDPIAware();
172168
#endif
173169
#endif
174-
Py_RETURN_NONE;
175170
}
176171

177-
static PyMethodDef functions[] = {
178-
{"display_is_valid", (PyCFunction)mpl_display_is_valid, METH_NOARGS,
179-
"display_is_valid()\n--\n\n"
180-
"Check whether the current X11 or Wayland display is valid.\n\n"
181-
"On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)\n"
182-
"succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)\n"
183-
"succeeds.\n\n"
184-
"On other platforms, always returns True."},
185-
{"Win32_GetCurrentProcessExplicitAppUserModelID",
186-
(PyCFunction)mpl_GetCurrentProcessExplicitAppUserModelID, METH_NOARGS,
187-
"Win32_GetCurrentProcessExplicitAppUserModelID()\n--\n\n"
188-
"Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID.\n\n"
189-
"On non-Windows platforms, always returns None."},
190-
{"Win32_SetCurrentProcessExplicitAppUserModelID",
191-
(PyCFunction)mpl_SetCurrentProcessExplicitAppUserModelID, METH_O,
192-
"Win32_SetCurrentProcessExplicitAppUserModelID(appid, /)\n--\n\n"
193-
"Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID.\n\n"
194-
"On non-Windows platforms, does nothing."},
195-
{"Win32_GetForegroundWindow",
196-
(PyCFunction)mpl_GetForegroundWindow, METH_NOARGS,
197-
"Win32_GetForegroundWindow()\n--\n\n"
198-
"Wrapper for Windows' GetForegroundWindow.\n\n"
199-
"On non-Windows platforms, always returns None."},
200-
{"Win32_SetForegroundWindow",
201-
(PyCFunction)mpl_SetForegroundWindow, METH_O,
202-
"Win32_SetForegroundWindow(hwnd, /)\n--\n\n"
203-
"Wrapper for Windows' SetForegroundWindow.\n\n"
204-
"On non-Windows platforms, does nothing."},
205-
{"Win32_SetProcessDpiAwareness_max",
206-
(PyCFunction)mpl_SetProcessDpiAwareness_max, METH_NOARGS,
207-
"Win32_SetProcessDpiAwareness_max()\n--\n\n"
208-
"Set Windows' process DPI awareness to best option available.\n\n"
209-
"On non-Windows platforms, does nothing."},
210-
{NULL, NULL}}; // sentinel.
211-
static PyModuleDef util_module = {
212-
PyModuleDef_HEAD_INIT, "_c_internal_utils", NULL, 0, functions
213-
};
214-
215-
#pragma GCC visibility push(default)
216-
PyMODINIT_FUNC PyInit__c_internal_utils(void)
172+
PYBIND11_MODULE(_c_internal_utils, m)
217173
{
218-
return PyModule_Create(&util_module);
174+
m.def(
175+
"display_is_valid", &mpl_display_is_valid,
176+
R"""( --
177+
Check whether the current X11 or Wayland display is valid.
178+
179+
On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)
180+
succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)
181+
succeeds.
182+
183+
On other platforms, always returns True.)""");
184+
m.def(
185+
"Win32_GetCurrentProcessExplicitAppUserModelID",
186+
&mpl_GetCurrentProcessExplicitAppUserModelID,
187+
R"""( --
188+
Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID.
189+
190+
On non-Windows platforms, always returns None.)""");
191+
m.def(
192+
"Win32_SetCurrentProcessExplicitAppUserModelID",
193+
&mpl_SetCurrentProcessExplicitAppUserModelID,
194+
"appid"_a, py::pos_only(),
195+
R"""( --
196+
Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID.
197+
198+
On non-Windows platforms, does nothing.)""");
199+
m.def(
200+
"Win32_GetForegroundWindow", &mpl_GetForegroundWindow,
201+
R"""( --
202+
Wrapper for Windows' GetForegroundWindow.
203+
204+
On non-Windows platforms, always returns None.)""");
205+
m.def(
206+
"Win32_SetForegroundWindow", &mpl_SetForegroundWindow,
207+
"hwnd"_a,
208+
R"""( --
209+
Wrapper for Windows' SetForegroundWindow.
210+
211+
On non-Windows platforms, does nothing.)""");
212+
m.def(
213+
"Win32_SetProcessDpiAwareness_max", &mpl_SetProcessDpiAwareness_max,
214+
R"""( --
215+
Set Windows' process DPI awareness to best option available.
216+
217+
On non-Windows platforms, does nothing.)""");
219218
}

src/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ extension_data = {
8484
'sources': files(
8585
'_c_internal_utils.cpp',
8686
),
87-
'dependencies': [py3_dep, dl, ole32, shell32, user32],
87+
'dependencies': [pybind11_dep, dl, ole32, shell32, user32],
8888
},
8989
'ft2font': {
9090
'subdir': 'matplotlib',

0 commit comments

Comments
 (0)
0