8000 Convert internal utilities to pybind11 · matplotlib/matplotlib@a567006 · 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 a567006

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

File tree

2 files changed

+87
-89
lines changed

2 files changed

+87
-89
lines changed

src/_c_internal_utils.cpp

Lines changed: 86 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
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+
24+
static bool
25+
mpl_display_is_valid(void)
2026
{
2127
#ifdef __linux__
2228
void* libX11;
@@ -34,11 +40,10 @@ mpl_display_is_valid(PyObject* module)
3440
XCloseDisplay(display);
3541
}
3642
if (dlclose(libX11)) {
37-
PyErr_SetString(PyExc_RuntimeError, dlerror());
38-
return NULL;
43+
throw std::runtime_error(dlerror());
3944
}
4045
if (display) {
41-
Py_RETURN_TRUE;
46+
return true;
4247
}
4348
}
4449
void* libwayland_client;
@@ -56,84 +61,74 @@ mpl_display_is_valid(PyObject* module)
5661
wl_display_disconnect(display);
5762
}
5863
if (dlclose(libwayland_client)) {
59-
PyErr_SetString(PyExc_RuntimeError, dlerror());
60-
return NULL;
64+
throw std::runtime_error(dlerror());
6165
}
6266
if (display) {
63-
Py_RETURN_TRUE;
67+
return true;
6468
}
6569
}
66-
Py_RETURN_FALSE;
70+
return false;
6771
#else
68-
Py_RETURN_TRUE;
72+
return true;
6973
#endif
7074
}
7175

72-
static PyObject*
73-
mpl_GetCurrentProcessExplicitAppUserModelID(PyObject* module)
76+
static py::object
77+
mpl_GetCurrentProcessExplicitAppUserModelID(void)
7478
{
7579
#ifdef _WIN32
7680
wchar_t* appid = NULL;
7781
HRESULT hr = GetCurrentProcessExplicitAppUserModelID(&appid);
7882
if (FAILED(hr)) {
79-
return PyErr_SetFromWindowsErr(hr);
83+
PyErr_SetFromWindowsErr(hr);
84+
throw py::error_already_set();
8085
}
81-
PyObject* py_appid = PyUnicode_FromWideChar(appid, -1);
86+
auto py_appid = py::cast(appid);
8287
CoTaskMemFree(appid);
8388
return py_appid;
8489
#else
85-
Py_RETURN_NONE;
90+
return py::none();
8691
#endif
8792
}
8893

89-
static PyObject*
90-
mpl_SetCurrentProcessExplicitAppUserModelID(PyObject* module, PyObject* arg)
94+
static void
95+
mpl_SetCurrentProcessExplicitAppUserModelID(const wchar_t* UNUSED_ON_NON_WINDOWS(appid))
9196
{
9297
#ifdef _WIN32
93-
wchar_t* appid = PyUnicode_AsWideCharString(arg, NULL);
94-
if (!appid) {
95-
return NULL;
96-
}
9798
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(appid);
98-
PyMem_Free(appid);
9999
if (FAILED(hr)) {
100-
return PyErr_SetFromWindowsErr(hr);
100+
PyErr_SetFromWindowsErr(hr);
101+
throw py::error_already_set();
101102
}
102-
Py_RETURN_NONE;
103-
#else
104-
Py_RETURN_NONE;
105103
#endif
106104
}
107105

108-
static PyObject*
109-
mpl_GetForegroundWindow(PyObject* module)
106+
static py::object
107+
mpl_GetForegroundWindow(void)
110108
{
111109
#ifdef _WIN32
112-
return PyLong_FromVoidPtr(GetForegroundWindow());
110+
return py::capsule(GetForegroundWindow(), "HWND");
113111
#else
114-
Py_RETURN_NONE;
112+
return py::none();
115113
#endif
116114
}
117115

118-
static PyObject*
119-
mpl_SetForegroundWindow(PyObject* module, PyObject *arg)
116+
static void
117+
mpl_SetForegroundWindow(py::capsule UNUSED_ON_NON_WINDOWS(handle_p))
120118
{
121119
#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;
120+
if (handle_p.name() != "HWND") {
121+
throw std::runtime_error("Handle must be a value returned from Win32_GetForegroundWindow");
122+
}
123+
HWND handle = static_cast<HWND>(handle_p.get_pointer());
124+
if (!SetForegroundWindow(handle)) {
125+
throw std::runtime_error("Error setting window");
126+
}
132127
#endif
133128
}
134129

135-
static PyObject*
136-
mpl_SetProcessDpiAwareness_max(PyObject* module)
130+
static void
131+
mpl_SetProcessDpiAwareness_max(void)
137132
{
138133
#ifdef _WIN32
139134
#ifdef _DPI_AWARENESS_CONTEXTS_
@@ -171,49 +166,52 @@ mpl_SetProcessDpiAwareness_max(PyObject* module)
171166
SetProcessDPIAware();
172167
#endif
173168
#endif
174-
Py_RETURN_NONE;
175169
}
176170

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-< 7802 /span>
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)
171+
PYBIND11_MODULE(_c_internal_utils, m)
217172
{
218-
return PyModule_Create(&util_module);
173+
m.def(
174+
"display_is_valid", &mpl_display_is_valid,
175+
R"""( --
176+
Check whether the current X11 or Wayland display is valid.
177+
178+
On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)
179+
succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)
180+
succeeds.
181+
182+
On other platforms, always returns True.)""");
183+
m.def(
184+
"Win32_GetCurrentProcessExplicitAppUserModelID",
185+
&mpl_GetCurrentProcessExplicitAppUserModelID,
186+
R"""( --
187+
Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID.
188+
189+
On non-Windows platforms, always returns None.)""");
190+
m.def(
191+
"Win32_SetCurrentProcessExplicitAppUserModelID",
192+
&mpl_SetCurrentProcessExplicitAppUserModelID,
193+
py::arg("appid"), py::pos_only(),
194+
R"""( --
195+
Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID.
196+
197+
On non-Windows platforms, does nothing.)""");
198+
m.def(
199+
"Win32_GetForegroundWindow", &mpl_GetForegroundWindow,
200+
R"""( --
201+
Wrapper for Windows' GetForegroundWindow.
202+
203+
On non-Windows platforms, always returns None.)""");
204+
m.def(
205+
"Win32_SetForegroundWindow", &mpl_SetForegroundWindow,
206+
py::arg("hwnd"),
207+
R"""( --
208+
Wrapper for Windows' SetForegroundWindow.
209+
210+
On non-Windows platforms, does nothing.)""");
211+
m.def(
212+
"Win32_SetProcessDpiAwareness_max", &mpl_SetProcessDpiAwareness_max,
213+
R"""( --
214+
Set Windows' process DPI awareness to best option available.
215+
216+
On non-Windows platforms, does nothing.)""");
219217
}

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