Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6270f03

Browse files
committed
Convert internal utilities to pybind11
1 parent 402b580 commit 6270f03

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*
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-
}
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-
(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+
&mpl_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)