mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[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:
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
15
wpiutil/src/test/python/test_wpi_string.py
Normal file
15
wpiutil/src/test/python/test_wpi_string.py
Normal 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
|
||||
Reference in New Issue
Block a user