[py][wpiutil] Add type caster for WPI_String (#8500)

This adds a type caster for `WPI_String` so that pybind11 can more
easily auto-convert between that and strings. This helps remove the need
to do things like
[this](f1d77244c3)
in the opmodes fixup
This commit is contained in:
PJ Reiniger
2025-12-31 12:03:24 -05:00
committed by GitHub
parent 632eb0922d
commit 1bbb284ad1
4 changed files with 86 additions and 0 deletions

View File

@@ -120,6 +120,10 @@ types = ["wpi::util::StringMap"]
header = "wpi_ct_string_type_caster.h"
types = ["wpi::util::ct_string"]
[[tool.semiwrap.export_type_casters.wpiutil-casters.headers]]
header = "wpi_string_type_caster.h"
types = ["WPI_String"]
[[tool.semiwrap.export_type_casters.wpiutil-casters.headers]]
header = "wpystruct.h"
types = ["WPyStruct"]

View File

@@ -0,0 +1,34 @@
#include <pybind11/pybind11.h>
#include "wpi/util/string.h"
namespace pybind11::detail {
template <>
struct type_caster<WPI_String> {
public:
PYBIND11_TYPE_CASTER(WPI_String, _("str"));
bool load(handle src, bool convert) {
if (!src) {
return false;
}
Py_ssize_t size = -1;
const char *str = PyUnicode_AsUTF8AndSize(src.ptr(), &size);
if (!str) {
PyErr_Clear();
return false;
}
value = WPI_String(str, static_cast<size_t>(size));
return true;
}
static handle cast(const WPI_String& str, return_value_policy /* policy */, handle /* parent */) {
return PyUnicode_FromStringAndSize(str.str, str.len);
}
};
} // namespace pybind11::detail

View File

@@ -9,6 +9,7 @@
#include <wpi_string_map_caster.h>
#include <wpi_json_type_caster.h>
#include <wpi_ct_string_type_caster.h>
#include <wpi_string_type_caster.h>
#include <limits>
#include <functional>
@@ -152,6 +153,29 @@ constexpr auto const_string() {
void sendable_test(py::module &m);
void struct_test(py::module &m);
/* WPI_String tests */
struct StructWithWPI_String {
int x;
WPI_String str;
};
WPI_String load_wpi_string(WPI_String str) {
return str;
}
WPI_String cast_wpi_string() {
WPI_String str = wpi::util::make_string("Hello WPI_String!");
return str;
}
StructWithWPI_String cast_struct_with_wpi_string() {
StructWithWPI_String output{
.x = 3504,
.str = wpi::util::make_string("I'm in a struct!")
};
return output;
}
PYBIND11_MODULE(module, m) {
@@ -192,4 +216,13 @@ PYBIND11_MODULE(module, m) {
m.attr("min_int64") = std::numeric_limits<int64_t>::min();
// ct_string
m.def("const_string", &const_string);
// WPI_String
m.def("load_wpi_string", &load_wpi_string);
m.def("cast_wpi_string", &cast_wpi_string);
py::class_<StructWithWPI_String> structWithWpiStringCls(m, "StructWithWPI_String");
structWithWpiStringCls.def_readwrite("x", &StructWithWPI_String::x);
structWithWpiStringCls.def_readonly("str", &StructWithWPI_String::str);
m.def("cast_struct_with_wpi_string", &cast_struct_with_wpi_string);
};

View File

@@ -0,0 +1,15 @@
from wpiutil_test import module
def test_wpi_string_load():
assert "Hello World" == module.load_wpi_string("Hello World")
def test_wpi_string_cast():
assert "Hello WPI_String!" == module.cast_wpi_string()
def test_wpi_string_in_struct_cast():
the_struct = module.cast_struct_with_wpi_string()
assert 3504 == the_struct.x
assert "I'm in a struct!" == the_struct.str