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

Browse files
committed
Convert internal utilities to pybind11
1 parent e0697d2 commit 0fca6f9

File tree

2 files changed

+82
-89
lines changed

2 files changed

+82
-89
lines changed

src/_c_internal_utils.cpp

Lines changed: 81 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
#define WINVER 0x0A00
55
#define _WIN32_WINNT 0x0A00
66
#endif
7-
#define PY_SSIZE_T_CLEAN
8-
#include <Python.h>
7+
#include <pybind11/pybind11.h>
98
#ifdef __linux__
109
#include <dlfcn.h>
1110
#endif
@@ -15,8 +14,10 @@
1514
#include <Windows.h>
1615
#endif
1716

18-
static PyObject*
< 10000 /td>
19-
mpl_display_is_valid(PyObject* module)
17+
namespace py = pybind11;
18+
19+
static bool
20+
mpl_display_is_valid(void)
2021
{
2122
#ifdef __linux__
2223
void* libX11;
@@ -34,11 +35,10 @@ mpl_display_is_valid(PyObject* module)
3435
XCloseDisplay(display);
3536
}
3637
if (dlclose(libX11)) {
37-
PyErr_SetString(PyExc_RuntimeError, dlerror());
38-
return NULL;
38+
throw std::runtime_error(dlerror());
3939
}
4040
if (display) {
41-
Py_RETURN_TRUE;
41+
return true;
4242
}
4343
}
4444
void* libwayland_client;
@@ -56,84 +56,74 @@ mpl_display_is_valid(PyObject* module)
5656
wl_display_disconnect(display);
5757
}
5858
if (dlclose(libwayland_client)) {
59-
PyErr_SetString(PyExc_RuntimeError, dlerror());
60-
return NULL;
59+
throw std::runtime_error(dlerror());
6160
}
6261
if (display) {
63-
Py_RETURN_TRUE;
62+
return true;
6463
}
6564
}
66-
Py_RETURN_FALSE;
65+
return false;
6766
#else
68-
Py_RETURN_TRUE;
67+
return true;
6968
#endif
7069
}
7170

72-
static PyObject*
73-
mpl_GetCurrentProcessExplicitAppUserModelID(PyObject* module)
71+
static py::object
72+
mpl_GetCurrentProcessExplicitAppUserModelID(void)
7473
{
7574
#ifdef _WIN32
7675
wchar_t* appid = NULL;
7776
HRESULT hr = GetCurrentProcessExplicitAppUserModelID(&appid);
7877
if (FAILED(hr)) {
79-
return PyErr_SetFromWindowsErr(hr);
78+
PyErr_SetFromWindowsErr(hr);
79+
throw py::error_already_set();
8080
}
81-
PyObject* py_appid = PyUnicode_FromWideChar(appid, -1);
81+
auto py_appid = py::cast(appid);
8282
CoTaskMemFree(appid);
8383
return py_appid;
8484
#else
85-
Py_RETURN_NONE;
85+
return py::none();
8686
#endif
8787
}
8888

89-
static PyObject*
90-
mpl_SetCurrentProcessExplicitAppUserModelID(PyObject* module, PyObject* arg)
89+
static void
90+
mpl_SetCurrentProcessExplicitAppUserModelID(wchar_t *appid)
9191
{
9292
#ifdef _WIN32
93-
wchar_t* appid = PyUnicode_AsWideCharString(arg, NULL);
94-
if (!appid) {
95-
return NULL;
96-
}
9793
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(appid);
98-
PyMem_Free(appid);
9994
if (FAILED(hr)) {
100-
return PyErr_SetFromWindowsErr(hr);
95+
PyErr_SetFromWindowsErr(hr);
96+
throw py::error_already_set();
10197
}
102-
Py_RETURN_NONE;
103-
#else
104-
Py_RETURN_NONE;
10598
#endif
10699
}
107100

108-
static PyObject*
109-
mpl_GetForegroundWindow(PyObject* module)
101+
static py::object
102+
mpl_GetForegroundWindow(void)
110103
{
111104
#ifdef _WIN32
112-
return PyLong_FromVoidPtr(GetForegroundWindow());
105+
return py::capsule(GetForegroundWindow(), "HWND");
113106
#else
114-
Py_RETURN_NONE;
107+
return py::none();
115108
#endif
116109
}
117110

118-
static PyObject*
119-
mpl_SetForegroundWindow(PyObject* module, PyObject *arg)
111+
static void
112+
mpl_SetForegroundWindow(py::capsule handle_p)
120113
{
121114
#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 10000 -
}
129-
Py_RETURN_NONE;
130-
#else
131-
Py_RETURN_NONE;
115+
if (handle_p.name() != "HWND") {
116+
throw std::runtime_error("Handle must be a value returned from Win32_GetForegroundWindow");
117+
}
118+
HWND handle = static_cast<HWND>(handle_p.get_pointer());
119+
if (!SetForegroundWindow(handle)) {
120+
throw std::runtime_error("Error setting window");
121+
}
132122
#endif
133123
}
134124

135-
static PyObject*
136-
mpl_SetProcessDpiAwareness_max(PyObject* module)
125+
static void
126+
mpl_SetProcessDpiAwareness_max(void)
137127
{
138128
#ifdef _WIN32
139129
#ifdef _DPI_AWARENESS_CONTEXTS_
@@ -171,49 +161,52 @@ mpl_SetProcessDpiAwareness_max(PyObject* module)
171161
SetProcessDPIAware();
172162
#endif
173163
#endif
174-
Py_RETURN_NONE;
175164
}
176165

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

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