mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-29 02:21:44 +00:00
[robotpy] Run wpiformat on non-python robotpy files (#8362)
This turns the styleguide on for the non-python robotpy files. The overwhelming amount of changes were related to whitespace, followed by some IWYU for standard library headers.
This commit is contained in:
@@ -13,7 +13,10 @@ generatedFileExclude {
|
||||
docs/theme\.css$
|
||||
generated/
|
||||
hal/src/main/native/systemcore/rev/
|
||||
python/
|
||||
|
||||
src/main/python/.*/type_casters/
|
||||
src/main/python/.*\.py$
|
||||
src/test/python/.*\.py$
|
||||
robotpyExamples/
|
||||
resources/
|
||||
thirdparty/
|
||||
@@ -41,4 +44,7 @@ licenseUpdateExclude {
|
||||
wpiutil/src/main/native/cpp/sha1\.cpp$
|
||||
wpiutil/src/main/native/include/wpi/util/sha1\.hpp$
|
||||
wpinet/src/main/native/linux/AvahiClient\.hpp$
|
||||
|
||||
src/main/python/
|
||||
src/test/python/
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
#include "semiwrap_init.robotpy_apriltag._apriltag.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) { initWrapper(m); }
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ classes:
|
||||
// We are going to move the detection result into this shared_ptr
|
||||
// so that python can keep it alive. We don't expose the result directly
|
||||
// to the user because we'd have to pretend it's a list, and that would
|
||||
// be annoying.
|
||||
// be annoying.
|
||||
std::shared_ptr<AprilTagDetector::Results> c_result;
|
||||
{
|
||||
py::gil_scoped_release unlock;
|
||||
|
||||
@@ -33,4 +33,4 @@ source = "vcs"
|
||||
packages = ["commands2"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["commands2"]
|
||||
packages = ["commands2"]
|
||||
|
||||
@@ -38,4 +38,4 @@ name = "datalog"
|
||||
includedir = "src/native/datalog/include"
|
||||
libdir = "src/native/datalog/lib"
|
||||
shared_libraries = ["datalog"]
|
||||
requires = ["robotpy-native-wpiutil"]
|
||||
requires = ["robotpy-native-wpiutil"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#include <semiwrap_init.wpilog._wpilog.hpp>
|
||||
#include "semiwrap_init.wpilog._wpilog.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
|
||||
#include <semiwrap_init.hal.simulation._simulation.hpp>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "semiwrap_init.hal.simulation._simulation.hpp"
|
||||
#include "sim_cb.h"
|
||||
#include "sim_value_cb.h"
|
||||
|
||||
void HALSIM_ResetGlobalHandles();
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
|
||||
py::class_<SimCB> cls_SimCB(m, "SimCB");
|
||||
cls_SimCB.doc() = "Simulation callback handle";
|
||||
cls_SimCB.def("cancel", &SimCB::Cancel, py::doc("Cancel the callback"));
|
||||
|
||||
py::class_<SimValueCB> cls_SimValueCB(m, "SimValueCB");
|
||||
cls_SimValueCB.doc() = "Simulation callback handle";
|
||||
cls_SimValueCB.def("cancel", &SimValueCB::Cancel, py::doc("Cancel the callback"));
|
||||
cls_SimValueCB.def("cancel", &SimValueCB::Cancel,
|
||||
py::doc("Cancel the callback"));
|
||||
|
||||
initWrapper(m);
|
||||
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
#include "wpi/hal/simulation/NotifierData.h"
|
||||
|
||||
void HALSIM_ResetGlobalHandles() {
|
||||
|
||||
// if we just reset the handles, notifiers might hang forever,
|
||||
// so we just enumerate and cancel them all
|
||||
auto sz = HALSIM_GetNotifierInfo(nullptr, 0);
|
||||
if (sz > 0) {
|
||||
struct HALSIM_NotifierInfo *info = new struct HALSIM_NotifierInfo[sz];
|
||||
struct HALSIM_NotifierInfo* info = new struct HALSIM_NotifierInfo[sz];
|
||||
HALSIM_GetNotifierInfo(info, sz);
|
||||
|
||||
for (int i = 0; i < sz; i++) {
|
||||
|
||||
@@ -1,33 +1,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
class SimCB {
|
||||
public:
|
||||
public:
|
||||
SimCB(std::function<void(void)> fn, std::function<void(int32_t)> cancel)
|
||||
: m_fn(fn), m_cancel(cancel) {}
|
||||
|
||||
SimCB(std::function<void(void)> fn, std::function<void(int32_t)> cancel) :
|
||||
m_fn(fn),
|
||||
m_cancel(cancel)
|
||||
{}
|
||||
void SetUID(int32_t uid) { m_uid = uid; }
|
||||
|
||||
void SetUID(int32_t uid) {
|
||||
m_uid = uid;
|
||||
~SimCB() { Cancel(); }
|
||||
|
||||
void Cancel() {
|
||||
if (m_valid) {
|
||||
m_cancel(m_uid);
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
~SimCB() {
|
||||
Cancel();
|
||||
}
|
||||
std::function<void(void)> m_fn;
|
||||
|
||||
void Cancel() {
|
||||
if (m_valid) {
|
||||
m_cancel(m_uid);
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(void)> m_fn;
|
||||
|
||||
private:
|
||||
bool m_valid = true;
|
||||
int32_t m_uid;
|
||||
std::function<void(int32_t)> m_cancel;
|
||||
};
|
||||
private:
|
||||
bool m_valid = true;
|
||||
int32_t m_uid;
|
||||
std::function<void(int32_t)> m_cancel;
|
||||
};
|
||||
|
||||
@@ -1,37 +1,33 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "wpi/hal/SimDevice.h"
|
||||
|
||||
class SimValueCB {
|
||||
public:
|
||||
public:
|
||||
using FnType = std::function<void(const char*, HAL_SimValueHandle,
|
||||
HAL_SimValueDirection, HAL_Value)>;
|
||||
|
||||
using FnType = std::function<void(const char *, HAL_SimValueHandle, HAL_SimValueDirection, HAL_Value)>;
|
||||
SimValueCB(FnType fn, std::function<void(int32_t)> cancel)
|
||||
: m_fn(fn), m_cancel(cancel) {}
|
||||
|
||||
SimValueCB(FnType fn, std::function<void(int32_t)> cancel) :
|
||||
m_fn(fn),
|
||||
m_cancel(cancel)
|
||||
{}
|
||||
void SetUID(int32_t uid) { m_uid = uid; }
|
||||
|
||||
void SetUID(int32_t uid) {
|
||||
m_uid = uid;
|
||||
~SimValueCB() { Cancel(); }
|
||||
|
||||
void Cancel() {
|
||||
if (m_valid) {
|
||||
m_cancel(m_uid);
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
~SimValueCB() {
|
||||
Cancel();
|
||||
}
|
||||
FnType m_fn;
|
||||
|
||||
void Cancel() {
|
||||
if (m_valid) {
|
||||
m_cancel(m_uid);
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
FnType m_fn;
|
||||
|
||||
private:
|
||||
bool m_valid = true;
|
||||
int32_t m_uid;
|
||||
std::function<void(int32_t)> m_cancel;
|
||||
};
|
||||
private:
|
||||
bool m_valid = true;
|
||||
int32_t m_uid;
|
||||
std::function<void(int32_t)> m_cancel;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include "wpi/hal/DriverStationTypes.h"
|
||||
@@ -8,23 +10,23 @@ namespace pybind11 {
|
||||
|
||||
template <>
|
||||
struct format_descriptor<HAL_JoystickPOV> {
|
||||
static constexpr const char c = 'B';
|
||||
static constexpr const char value[2] = {c, '\0'};
|
||||
static std::string format() { return std::string(1, c); }
|
||||
static constexpr const char c = 'B';
|
||||
static constexpr const char value[2] = {c, '\0'};
|
||||
static std::string format() { return std::string(1, c); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct format_descriptor<HAL_JoystickTouchpad> {
|
||||
static constexpr const char c = 'B';
|
||||
static constexpr const char value[2] = {c, '\0'};
|
||||
static std::string format() { return std::string(1, c); }
|
||||
static constexpr const char c = 'B';
|
||||
static constexpr const char value[2] = {c, '\0'};
|
||||
static std::string format() { return std::string(1, c); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct format_descriptor<HAL_JoystickTouchpadFinger> {
|
||||
static constexpr const char c = 'B';
|
||||
static constexpr const char value[2] = {c, '\0'};
|
||||
static std::string format() { return std::string(1, c); }
|
||||
static constexpr const char c = 'B';
|
||||
static constexpr const char value[2] = {c, '\0'};
|
||||
static std::string format() { return std::string(1, c); }
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace pybind11
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
|
||||
|
||||
#include "wpi/hal/HAL.h"
|
||||
|
||||
#include "semiwrap_init.hal._wpiHal.hpp"
|
||||
#include "wpi/hal/DriverStation.hpp"
|
||||
#include "wpi/hal/Value.h"
|
||||
#include <semiwrap_init.hal._wpiHal.hpp>
|
||||
|
||||
using namespace pybind11::literals;
|
||||
|
||||
static py::module_ sys_module;
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
|
||||
// Add this manually so it can be used from SimValue
|
||||
py::enum_<HAL_Type>(m, "Type")
|
||||
.value("UNASSIGNED", HAL_Type::HAL_UNASSIGNED)
|
||||
.value("BOOLEAN", HAL_Type::HAL_BOOLEAN)
|
||||
.value("DOUBLE", HAL_Type::HAL_DOUBLE)
|
||||
.value("ENUM", HAL_Type::HAL_ENUM)
|
||||
.value("INT", HAL_Type::HAL_INT)
|
||||
.value("LONG", HAL_Type::HAL_LONG);
|
||||
.value("UNASSIGNED", HAL_Type::HAL_UNASSIGNED)
|
||||
.value("BOOLEAN", HAL_Type::HAL_BOOLEAN)
|
||||
.value("DOUBLE", HAL_Type::HAL_DOUBLE)
|
||||
.value("ENUM", HAL_Type::HAL_ENUM)
|
||||
.value("INT", HAL_Type::HAL_INT)
|
||||
.value("LONG", HAL_Type::HAL_LONG);
|
||||
|
||||
// clang-format off
|
||||
// Add this manually because it would be annoying to do otherwise
|
||||
py::class_<HAL_Value>(m, "Value")
|
||||
.def_readonly("type", &HAL_Value::type)
|
||||
@@ -57,6 +58,7 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
return "<Value type=invalid>";
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
initWrapper(m);
|
||||
|
||||
@@ -67,15 +69,18 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
m.attr("__halplatform__") = "sim";
|
||||
m.attr("__hal_simulation__") = true;
|
||||
|
||||
// clang-format off
|
||||
m.def("__test_senderr", []() {
|
||||
wpi::hal::SendError(1, 2, "\xfa" "badmessage", "location", "callstack", 1);
|
||||
}, release_gil());
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
||||
// Redirect stderr to python stderr
|
||||
sys_module = py::module_::import("sys");
|
||||
|
||||
// clang-format off
|
||||
HAL_SetPrintErrorImpl([](const struct WPI_String* line) {
|
||||
if (line == nullptr || line->str == nullptr || line->len == 0) {
|
||||
return;
|
||||
@@ -90,7 +95,9 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
py::print(py::reinterpret_steal<py::str>(o), "file"_a=sys_module.attr("stderr"));
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
// Do cleanup on module unload
|
||||
static int unused; // the capsule needs something to reference
|
||||
py::capsule cleanup(&unused, [](void *) {
|
||||
@@ -106,5 +113,6 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
HAL_Shutdown();
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
m.add_object("_cleanup", cleanup);
|
||||
}
|
||||
|
||||
@@ -60,4 +60,4 @@ name = "wpihal"
|
||||
includedir = "src/native/wpihal/include"
|
||||
libdir = "src/native/wpihal/lib"
|
||||
shared_libraries = ["wpiHal"]
|
||||
requires = ["robotpy-native-wpiutil", "robotpy-native-ntcore", "robotpy-native-mrclib"]
|
||||
requires = ["robotpy-native-wpiutil", "robotpy-native-ntcore", "robotpy-native-mrclib"]
|
||||
|
||||
@@ -10,4 +10,3 @@ strip_prefixes:
|
||||
|
||||
enums:
|
||||
HAL_SimValueDirection:
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
// clang-format off
|
||||
cls_NetworkTable
|
||||
.def("getValue", [](const NetworkTable &self, std::string_view key, py::object defaultValue) -> py::object {
|
||||
wpi::nt::NetworkTableEntry entry;
|
||||
@@ -54,3 +60,4 @@ cls_NetworkTable
|
||||
return self.ContainsKey(key);
|
||||
}, release_gil())
|
||||
;
|
||||
// clang-format on
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
// clang-format off
|
||||
cls_NetworkTableEntry
|
||||
.def_property_readonly("value", [](const wpi::nt::NetworkTableEntry &self) {
|
||||
wpi::nt::Value v;
|
||||
@@ -46,3 +51,4 @@ cls_NetworkTableEntry
|
||||
return self->SetDefaultValue(pyntcore::py2ntvalue(value));
|
||||
}, py::arg("value"))
|
||||
;
|
||||
// clang-format on
|
||||
|
||||
@@ -1,56 +1,61 @@
|
||||
#include <semiwrap.h>
|
||||
#include "nt_instance.h"
|
||||
#include "wpi/nt/ntcore_cpp.hpp"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/nt/ntcore_cpp.hpp"
|
||||
|
||||
// only accessed under GIL
|
||||
static std::set<NT_Inst> g_known_instances;
|
||||
|
||||
namespace pyntcore {
|
||||
|
||||
void onInstanceStart(wpi::nt::NetworkTableInstance *instance) {
|
||||
g_known_instances.emplace(instance->GetHandle());
|
||||
void onInstanceStart(wpi::nt::NetworkTableInstance* instance) {
|
||||
g_known_instances.emplace(instance->GetHandle());
|
||||
|
||||
py::module::import("ntcore._logutil")
|
||||
.attr("NtLogForwarder").attr("onInstanceStart")(instance);
|
||||
py::module::import("ntcore._logutil")
|
||||
.attr("NtLogForwarder")
|
||||
.attr("onInstanceStart")(instance);
|
||||
}
|
||||
|
||||
void onInstancePreReset(wpi::nt::NetworkTableInstance *instance) {
|
||||
py::module::import("ntcore._logutil")
|
||||
.attr("NtLogForwarder").attr("onInstanceDestroy")(instance);
|
||||
void onInstancePreReset(wpi::nt::NetworkTableInstance* instance) {
|
||||
py::module::import("ntcore._logutil")
|
||||
.attr("NtLogForwarder")
|
||||
.attr("onInstanceDestroy")(instance);
|
||||
}
|
||||
|
||||
void onInstancePostReset(wpi::nt::NetworkTableInstance *instance) {
|
||||
py::module::import("ntcore.util")
|
||||
.attr("_NtProperty").attr("onInstancePostReset")(instance);
|
||||
void onInstancePostReset(wpi::nt::NetworkTableInstance* instance) {
|
||||
py::module::import("ntcore.util")
|
||||
.attr("_NtProperty")
|
||||
.attr("onInstancePostReset")(instance);
|
||||
}
|
||||
|
||||
void onInstanceDestroy(wpi::nt::NetworkTableInstance *instance) {
|
||||
py::module::import("ntcore._logutil")
|
||||
.attr("NtLogForwarder").attr("onInstanceDestroy")(instance);
|
||||
py::module::import("ntcore.util")
|
||||
.attr("_NtProperty").attr("onInstanceDestroy")(instance);
|
||||
void onInstanceDestroy(wpi::nt::NetworkTableInstance* instance) {
|
||||
py::module::import("ntcore._logutil")
|
||||
.attr("NtLogForwarder")
|
||||
.attr("onInstanceDestroy")(instance);
|
||||
py::module::import("ntcore.util")
|
||||
.attr("_NtProperty")
|
||||
.attr("onInstanceDestroy")(instance);
|
||||
|
||||
g_known_instances.erase(instance->GetHandle());
|
||||
g_known_instances.erase(instance->GetHandle());
|
||||
}
|
||||
|
||||
// reset all instances to clear out any potential python references that
|
||||
// might be hanging around in a callback or something
|
||||
void resetAllInstances()
|
||||
{
|
||||
std::set<NT_Inst> known_instances;
|
||||
known_instances.swap(g_known_instances);
|
||||
void resetAllInstances() {
|
||||
std::set<NT_Inst> known_instances;
|
||||
known_instances.swap(g_known_instances);
|
||||
|
||||
// always reset the default instance
|
||||
known_instances.emplace(wpi::nt::GetDefaultInstance());
|
||||
// always reset the default instance
|
||||
known_instances.emplace(wpi::nt::GetDefaultInstance());
|
||||
|
||||
py::gil_scoped_release unlock;
|
||||
py::gil_scoped_release unlock;
|
||||
|
||||
for (auto &inst: known_instances) {
|
||||
wpi::nt::ResetInstance(inst);
|
||||
}
|
||||
for (auto& inst : known_instances) {
|
||||
wpi::nt::ResetInstance(inst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}; // namespace pyntcore
|
||||
} // namespace pyntcore
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wpi/nt/ntcore.h"
|
||||
#include "wpi/nt/NetworkTableInstance.hpp"
|
||||
#include "wpi/nt/ntcore.h"
|
||||
|
||||
namespace pyntcore {
|
||||
|
||||
void onInstanceStart(wpi::nt::NetworkTableInstance *instance);
|
||||
void onInstancePreReset(wpi::nt::NetworkTableInstance *instance);
|
||||
void onInstancePostReset(wpi::nt::NetworkTableInstance *instance);
|
||||
void onInstanceDestroy(wpi::nt::NetworkTableInstance *instance);
|
||||
void onInstanceStart(wpi::nt::NetworkTableInstance* instance);
|
||||
void onInstancePreReset(wpi::nt::NetworkTableInstance* instance);
|
||||
void onInstancePostReset(wpi::nt::NetworkTableInstance* instance);
|
||||
void onInstanceDestroy(wpi::nt::NetworkTableInstance* instance);
|
||||
|
||||
void resetAllInstances();
|
||||
|
||||
}; // namespace pyntcore
|
||||
} // namespace pyntcore
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
namespace pybind11 {
|
||||
namespace detail {
|
||||
namespace pybind11::detail {
|
||||
|
||||
// ntcore uses std::vector<uint8_t> anytime there is a raw value, so
|
||||
// add this specialization to convert to/from bytes directly
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct type_caster<std::vector<uint8_t>> {
|
||||
using vector_type = std::vector<uint8_t>;
|
||||
PYBIND11_TYPE_CASTER(vector_type, const_name("bytes"));
|
||||
using vector_type = std::vector<uint8_t>;
|
||||
PYBIND11_TYPE_CASTER(vector_type, const_name("bytes"));
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<buffer>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto buf = reinterpret_borrow<buffer>(src);
|
||||
auto req = buf.request();
|
||||
if (req.ndim != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto begin = (const uint8_t*)req.ptr;
|
||||
auto end = begin + req.size*req.itemsize;
|
||||
|
||||
value = std::vector<uint8_t>(begin, end);
|
||||
return true;
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<buffer>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto buf = reinterpret_borrow<buffer>(src);
|
||||
auto req = buf.request();
|
||||
if (req.ndim != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static handle cast(const std::vector<uint8_t> &src, return_value_policy policy, handle parent) {
|
||||
return py::bytes((char*)src.data(), src.size()).release();
|
||||
}
|
||||
auto begin = (const uint8_t*)req.ptr;
|
||||
auto end = begin + req.size * req.itemsize;
|
||||
|
||||
value = std::vector<uint8_t>(begin, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
static handle cast(const std::vector<uint8_t>& src,
|
||||
return_value_policy policy, handle parent) {
|
||||
return py::bytes(reinterpret_cast<const char*>(src.data()), src.size())
|
||||
.release();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace pybind11::detail
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
|
||||
#include <semiwrap_init.ntcore._ntcore.hpp>
|
||||
#include "nt_instance.h"
|
||||
#include "semiwrap_init.ntcore._ntcore.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
|
||||
static int unused;
|
||||
py::capsule cleanup(&unused, [](void *) {
|
||||
pyntcore::resetAllInstances();
|
||||
});
|
||||
py::capsule cleanup(&unused, [](void*) { pyntcore::resetAllInstances(); });
|
||||
|
||||
m.add_object("_st_cleanup", cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +1,110 @@
|
||||
|
||||
#include "py2value.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// type casters
|
||||
#include <pybind11/stl.h>
|
||||
#include <wpi_span_type_caster.h>
|
||||
|
||||
|
||||
|
||||
namespace pyntcore {
|
||||
|
||||
const char * nttype2str(NT_Type type) {
|
||||
const char* nttype2str(NT_Type type) {
|
||||
switch (type) {
|
||||
case NT_BOOLEAN:
|
||||
return "bool";
|
||||
case NT_DOUBLE:
|
||||
return "double";
|
||||
case NT_STRING:
|
||||
return "string";
|
||||
case NT_RAW:
|
||||
return "raw";
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
return "bool[]";
|
||||
case NT_DOUBLE_ARRAY:
|
||||
return "double[]";
|
||||
case NT_STRING_ARRAY:
|
||||
return "string[]";
|
||||
case NT_INTEGER:
|
||||
return "int";
|
||||
case NT_FLOAT:
|
||||
return "float";
|
||||
case NT_INTEGER_ARRAY:
|
||||
return "int[]";
|
||||
case NT_FLOAT_ARRAY:
|
||||
return "float[]";
|
||||
default:
|
||||
return "invalid";
|
||||
case NT_BOOLEAN:
|
||||
return "bool";
|
||||
case NT_DOUBLE:
|
||||
return "double";
|
||||
case NT_STRING:
|
||||
return "string";
|
||||
case NT_RAW:
|
||||
return "raw";
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
return "bool[]";
|
||||
case NT_DOUBLE_ARRAY:
|
||||
return "double[]";
|
||||
case NT_STRING_ARRAY:
|
||||
return "string[]";
|
||||
case NT_INTEGER:
|
||||
return "int";
|
||||
case NT_FLOAT:
|
||||
return "float";
|
||||
case NT_INTEGER_ARRAY:
|
||||
return "int[]";
|
||||
case NT_FLOAT_ARRAY:
|
||||
return "float[]";
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
py::object ntvalue2py(const wpi::nt::Value &ntvalue) {
|
||||
auto &v = ntvalue.value();
|
||||
py::object ntvalue2py(const wpi::nt::Value& ntvalue) {
|
||||
auto& v = ntvalue.value();
|
||||
switch (v.type) {
|
||||
case NT_BOOLEAN:
|
||||
return py::bool_(v.data.v_boolean);
|
||||
case NT_BOOLEAN:
|
||||
return py::bool_(v.data.v_boolean);
|
||||
|
||||
case NT_DOUBLE:
|
||||
return py::float_(v.data.v_double);
|
||||
case NT_DOUBLE:
|
||||
return py::float_(v.data.v_double);
|
||||
|
||||
case NT_STRING:
|
||||
return py::str(v.data.v_string.str, v.data.v_string.len);
|
||||
case NT_STRING:
|
||||
return py::str(v.data.v_string.str, v.data.v_string.len);
|
||||
|
||||
case NT_RAW:
|
||||
return py::bytes((const char *)v.data.v_raw.data, v.data.v_raw.size);
|
||||
case NT_RAW:
|
||||
return py::bytes((const char*)v.data.v_raw.data, v.data.v_raw.size);
|
||||
|
||||
case NT_BOOLEAN_ARRAY: {
|
||||
py::list l(v.data.arr_boolean.size);
|
||||
for (size_t i = 0; i < v.data.arr_boolean.size; i++) {
|
||||
auto b = py::bool_(v.data.arr_boolean.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, b.release().ptr());
|
||||
case NT_BOOLEAN_ARRAY: {
|
||||
py::list l(v.data.arr_boolean.size);
|
||||
for (size_t i = 0; i < v.data.arr_boolean.size; i++) {
|
||||
auto b = py::bool_(v.data.arr_boolean.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, b.release().ptr());
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
case NT_DOUBLE_ARRAY: {
|
||||
py::list l(v.data.arr_double.size);
|
||||
for (size_t i = 0; i < v.data.arr_double.size; i++) {
|
||||
auto d = py::float_(v.data.arr_double.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, d.release().ptr());
|
||||
case NT_DOUBLE_ARRAY: {
|
||||
py::list l(v.data.arr_double.size);
|
||||
for (size_t i = 0; i < v.data.arr_double.size; i++) {
|
||||
auto d = py::float_(v.data.arr_double.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, d.release().ptr());
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
case NT_STRING_ARRAY: {
|
||||
return py::cast(ntvalue.GetStringArray());
|
||||
}
|
||||
|
||||
case NT_INTEGER: {
|
||||
return py::int_(v.data.v_int);
|
||||
}
|
||||
|
||||
case NT_FLOAT: {
|
||||
return py::float_(v.data.v_float);
|
||||
}
|
||||
|
||||
case NT_INTEGER_ARRAY: {
|
||||
py::list l(v.data.arr_int.size);
|
||||
for (size_t i = 0; i < v.data.arr_int.size; i++) {
|
||||
auto d = py::int_(v.data.arr_int.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, d.release().ptr());
|
||||
case NT_STRING_ARRAY: {
|
||||
return py::cast(ntvalue.GetStringArray());
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
case NT_FLOAT_ARRAY: {
|
||||
py::list l(v.data.arr_float.size);
|
||||
for (size_t i = 0; i < v.data.arr_float.size; i++) {
|
||||
auto d = py::float_(v.data.arr_float.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, d.release().ptr());
|
||||
case NT_INTEGER: {
|
||||
return py::int_(v.data.v_int);
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
default:
|
||||
return py::none();
|
||||
case NT_FLOAT: {
|
||||
return py::float_(v.data.v_float);
|
||||
}
|
||||
|
||||
case NT_INTEGER_ARRAY: {
|
||||
py::list l(v.data.arr_int.size);
|
||||
for (size_t i = 0; i < v.data.arr_int.size; i++) {
|
||||
auto d = py::int_(v.data.arr_int.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, d.release().ptr());
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
case NT_FLOAT_ARRAY: {
|
||||
py::list l(v.data.arr_float.size);
|
||||
for (size_t i = 0; i < v.data.arr_float.size; i++) {
|
||||
auto d = py::float_(v.data.arr_float.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, d.release().ptr());
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
default:
|
||||
return py::none();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,38 +142,39 @@ wpi::nt::Value py2ntvalue(py::handle h) {
|
||||
auto v = h.cast<std::vector<std::string>>();
|
||||
return wpi::nt::Value::MakeStringArray(v);
|
||||
} else {
|
||||
throw py::value_error("Can only put bool/int/float/str/bytes or lists/tuples of them");
|
||||
throw py::value_error(
|
||||
"Can only put bool/int/float/str/bytes or lists/tuples of them");
|
||||
}
|
||||
}
|
||||
|
||||
py::function valueFactoryByType(wpi::nt::NetworkTableType type) {
|
||||
py::object PyNtValue = py::module::import("ntcore").attr("Value");
|
||||
switch (type) {
|
||||
case wpi::nt::NetworkTableType::BOOLEAN:
|
||||
return PyNtValue.attr("makeBoolean");
|
||||
case wpi::nt::NetworkTableType::DOUBLE:
|
||||
return PyNtValue.attr("makeDouble");
|
||||
case wpi::nt::NetworkTableType::STRING:
|
||||
return PyNtValue.attr("makeString");
|
||||
case wpi::nt::NetworkTableType::RAW:
|
||||
return PyNtValue.attr("makeRaw");
|
||||
case wpi::nt::NetworkTableType::BOOLEAN_ARRAY:
|
||||
return PyNtValue.attr("makeBooleanArray");
|
||||
case wpi::nt::NetworkTableType::DOUBLE_ARRAY:
|
||||
return PyNtValue.attr("makeDoubleArray");
|
||||
case wpi::nt::NetworkTableType::STRING_ARRAY:
|
||||
return PyNtValue.attr("makeStringArray");
|
||||
case wpi::nt::NetworkTableType::INTEGER:
|
||||
return PyNtValue.attr("makeInteger");
|
||||
case wpi::nt::NetworkTableType::FLOAT:
|
||||
return PyNtValue.attr("makeFloat");
|
||||
case wpi::nt::NetworkTableType::INTEGER_ARRAY:
|
||||
return PyNtValue.attr("makeIntegerArray");
|
||||
case wpi::nt::NetworkTableType::FLOAT_ARRAY:
|
||||
return PyNtValue.attr("makeFloatArray");
|
||||
default:
|
||||
throw py::type_error("empty nt value");
|
||||
case wpi::nt::NetworkTableType::BOOLEAN:
|
||||
return PyNtValue.attr("makeBoolean");
|
||||
case wpi::nt::NetworkTableType::DOUBLE:
|
||||
return PyNtValue.attr("makeDouble");
|
||||
case wpi::nt::NetworkTableType::STRING:
|
||||
return PyNtValue.attr("makeString");
|
||||
case wpi::nt::NetworkTableType::RAW:
|
||||
return PyNtValue.attr("makeRaw");
|
||||
case wpi::nt::NetworkTableType::BOOLEAN_ARRAY:
|
||||
return PyNtValue.attr("makeBooleanArray");
|
||||
case wpi::nt::NetworkTableType::DOUBLE_ARRAY:
|
||||
return PyNtValue.attr("makeDoubleArray");
|
||||
case wpi::nt::NetworkTableType::STRING_ARRAY:
|
||||
return PyNtValue.attr("makeStringArray");
|
||||
case wpi::nt::NetworkTableType::INTEGER:
|
||||
return PyNtValue.attr("makeInteger");
|
||||
case wpi::nt::NetworkTableType::FLOAT:
|
||||
return PyNtValue.attr("makeFloat");
|
||||
case wpi::nt::NetworkTableType::INTEGER_ARRAY:
|
||||
return PyNtValue.attr("makeIntegerArray");
|
||||
case wpi::nt::NetworkTableType::FLOAT_ARRAY:
|
||||
return PyNtValue.attr("makeFloatArray");
|
||||
default:
|
||||
throw py::type_error("empty nt value");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace pyntcore
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <semiwrap.h>
|
||||
#include "wpi/nt/NetworkTableValue.hpp"
|
||||
#include "wpi/nt/NetworkTableType.hpp"
|
||||
#include <fmt/format.h>
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/nt/NetworkTableType.hpp"
|
||||
#include "wpi/nt/NetworkTableValue.hpp"
|
||||
|
||||
namespace pyntcore {
|
||||
|
||||
const char * nttype2str(NT_Type type);
|
||||
const char* nttype2str(NT_Type type);
|
||||
|
||||
py::object ntvalue2py(const wpi::nt::Value &ntvalue);
|
||||
py::object ntvalue2py(const wpi::nt::Value& ntvalue);
|
||||
|
||||
wpi::nt::Value py2ntvalue(py::handle h);
|
||||
|
||||
py::function valueFactoryByType(wpi::nt::NetworkTableType type);
|
||||
|
||||
inline void ensure_value_is(NT_Type expected, wpi::nt::Value *v) {
|
||||
if (v->type() != expected) {
|
||||
throw py::value_error(fmt::format(
|
||||
"Value type is {}, not {}", nttype2str(v->type()), nttype2str(expected)
|
||||
));
|
||||
}
|
||||
inline void ensure_value_is(NT_Type expected, wpi::nt::Value* v) {
|
||||
if (v->type() != expected) {
|
||||
throw py::value_error(fmt::format("Value type is {}, not {}",
|
||||
nttype2str(v->type()),
|
||||
nttype2str(expected)));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace pyntcore
|
||||
|
||||
@@ -1,141 +1,179 @@
|
||||
|
||||
#include "pyentry.h"
|
||||
#include "py2value.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <pybind11/stl.h>
|
||||
#include <wpi_span_type_caster.h>
|
||||
|
||||
#include "py2value.h"
|
||||
|
||||
namespace pyntcore {
|
||||
|
||||
py::object GetBooleanEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_BOOLEAN) return defaultValue;
|
||||
return py::cast(value.GetBoolean());
|
||||
py::object GetBooleanEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_BOOLEAN) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetBoolean());
|
||||
}
|
||||
|
||||
py::object GetDoubleEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_DOUBLE) return defaultValue;
|
||||
return py::cast(value.GetDouble());
|
||||
py::object GetDoubleEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_DOUBLE) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetDouble());
|
||||
}
|
||||
|
||||
py::object GetFloatEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_FLOAT) return defaultValue;
|
||||
return py::cast(value.GetFloat());
|
||||
py::object GetFloatEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_FLOAT) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetFloat());
|
||||
}
|
||||
|
||||
py::object GetIntegerEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_INTEGER) return defaultValue;
|
||||
return py::cast(value.GetInteger());
|
||||
py::object GetIntegerEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_INTEGER) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetInteger());
|
||||
}
|
||||
|
||||
|
||||
py::object GetStringEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_STRING) return defaultValue;
|
||||
auto s = value.GetString();
|
||||
return py::str(s.data(), s.size());
|
||||
py::object GetStringEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_STRING) {
|
||||
return defaultValue;
|
||||
}
|
||||
auto s = value.GetString();
|
||||
return py::str(s.data(), s.size());
|
||||
}
|
||||
|
||||
py::object GetRawEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_RAW) return defaultValue;
|
||||
return py::cast(value.GetRaw());
|
||||
py::object GetRawEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_RAW) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetRaw());
|
||||
}
|
||||
|
||||
py::object GetBooleanArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_BOOLEAN_ARRAY) return defaultValue;
|
||||
// ntcore will return bit vector by default. Convert to List[bool]
|
||||
auto v = value.value();
|
||||
py::list l(v.data.arr_boolean.size);
|
||||
for (size_t i = 0; i < v.data.arr_boolean.size; i++) {
|
||||
auto b = py::bool_(v.data.arr_boolean.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, b.release().ptr());
|
||||
}
|
||||
return std::move(l);
|
||||
py::object GetBooleanArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_BOOLEAN_ARRAY) {
|
||||
return defaultValue;
|
||||
}
|
||||
// ntcore will return bit vector by default. Convert to List[bool]
|
||||
auto v = value.value();
|
||||
py::list l(v.data.arr_boolean.size);
|
||||
for (size_t i = 0; i < v.data.arr_boolean.size; i++) {
|
||||
auto b = py::bool_(v.data.arr_boolean.arr[i]);
|
||||
PyList_SET_ITEM(l.ptr(), i, b.release().ptr());
|
||||
}
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
py::object GetDoubleArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_DOUBLE_ARRAY) return defaultValue;
|
||||
return py::cast(value.GetDoubleArray());
|
||||
py::object GetDoubleArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_DOUBLE_ARRAY) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetDoubleArray());
|
||||
}
|
||||
|
||||
py::object GetFloatArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_FLOAT_ARRAY) return defaultValue;
|
||||
return py::cast(value.GetFloatArray());
|
||||
py::object GetFloatArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_FLOAT_ARRAY) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetFloatArray());
|
||||
}
|
||||
|
||||
py::object GetIntegerArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_INTEGER_ARRAY) return defaultValue;
|
||||
return py::cast(value.GetIntegerArray());
|
||||
py::object GetIntegerArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_INTEGER_ARRAY) {
|
||||
return defaultValue;
|
||||
}
|
||||
return py::cast(value.GetIntegerArray());
|
||||
}
|
||||
|
||||
py::object GetStringArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_STRING_ARRAY) return defaultValue;
|
||||
std::span<const std::string> rval = value.GetStringArray();
|
||||
return py::cast(rval);
|
||||
py::object GetStringArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value || value.type() != NT_STRING_ARRAY) {
|
||||
return defaultValue;
|
||||
}
|
||||
std::span<const std::string> rval = value.GetStringArray();
|
||||
return py::cast(rval);
|
||||
}
|
||||
|
||||
py::object GetValueEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value) return defaultValue;
|
||||
return ntvalue2py(value);
|
||||
py::object GetValueEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue) {
|
||||
wpi::nt::Value value;
|
||||
{
|
||||
py::gil_scoped_release release;
|
||||
value = wpi::nt::GetEntryValue(entry.GetHandle());
|
||||
}
|
||||
if (!value) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ntvalue2py(value);
|
||||
}
|
||||
|
||||
|
||||
}; // pyntcore
|
||||
} // namespace pyntcore
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/nt/NetworkTableEntry.hpp"
|
||||
#include "wpi/nt/NetworkTableValue.hpp"
|
||||
|
||||
namespace pyntcore {
|
||||
|
||||
py::object GetBooleanEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetDoubleEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetFloatEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetIntegerEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetStringEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetRawEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetBooleanArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetDoubleArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetFloatArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetIntegerArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetStringArrayEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetValueEntry(const wpi::nt::NetworkTableEntry &entry, py::object defaultValue);
|
||||
py::object GetBooleanEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetDoubleEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetFloatEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetIntegerEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetStringEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetRawEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetBooleanArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetDoubleArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetFloatArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetIntegerArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetStringArrayEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
py::object GetValueEntry(const wpi::nt::NetworkTableEntry& entry,
|
||||
py::object defaultValue);
|
||||
|
||||
};
|
||||
} // namespace pyntcore
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "wpi/nt/NetworkTableValue.hpp"
|
||||
#include "wpi/util/raw_ostream.hpp"
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace wpi::nt::net {
|
||||
namespace {
|
||||
|
||||
@@ -119,6 +117,7 @@ std::pair<int, Value> DecodeBinary(std::span<const uint8_t> data,
|
||||
}
|
||||
|
||||
ClientMessage Publish(int pubuid, std::string_view name) {
|
||||
using namespace std::literals;
|
||||
return ClientMessage{PublishMsg{
|
||||
pubuid, std::string{name}, "double"s, wpi::util::json::object(), {}}};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#include <semiwrap_init.romi._romi.hpp>
|
||||
#include "semiwrap_init.romi._romi.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[build-system]
|
||||
build-backend = "hatchling.build"
|
||||
requires = [
|
||||
"hatchling",
|
||||
"hatchling",
|
||||
"hatch-robotpy~=0.2.1",
|
||||
]
|
||||
|
||||
@@ -38,4 +38,4 @@ libs = ["halsim_ds_socket"]
|
||||
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["halsim_ds_socket"]
|
||||
packages = ["halsim_ds_socket"]
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
|
||||
#include <semiwrap_init.halsim_gui._ext._halsim_gui_ext.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <wpi/halsim/gui/HALSimGuiExt.hpp>
|
||||
#include <wpi/hal/Extensions.h>
|
||||
#include <wpi/halsim/gui/HALSimGuiExt.hpp>
|
||||
|
||||
#include "semiwrap_init.halsim_gui._ext._halsim_gui_ext.hpp"
|
||||
|
||||
std::function<void()> g_gui_exit;
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
|
||||
initWrapper(m);
|
||||
|
||||
m.def("_kill_on_signal", []() {
|
||||
HAL_RegisterExtensionListener(
|
||||
nullptr, [](void *, const char *name, void *data) {
|
||||
nullptr, [](void*, const char* name, void* data) {
|
||||
std::string_view name_view{name};
|
||||
if (name_view == HALSIMGUI_EXT_GUIEXIT) {
|
||||
g_gui_exit = (halsimgui::GuiExitFn)data;
|
||||
@@ -23,14 +22,14 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
AddGuiLateExecute([] {
|
||||
py::gil_scoped_acquire gil;
|
||||
if (PyErr_CheckSignals() == -1) {
|
||||
|
||||
// If a python signal has been triggered, the GUI needs to exit. It's
|
||||
// not safe to throw an exception here on all platforms so we just
|
||||
// assume that the only eventual caller of this function is HAL_RunMain,
|
||||
// and our wrapper around that function will check if a python error is
|
||||
// set and throw from there.
|
||||
// If a python signal has been triggered, the GUI needs to exit.
|
||||
// It's not safe to throw an exception here on all platforms so
|
||||
// we just assume that the only eventual caller of this function
|
||||
// is HAL_RunMain, and our wrapper around that function will
|
||||
// check if a python error is set and throw from there.
|
||||
//
|
||||
// Reference: https://github.com/wpilibsuite/allwpilib/issues/8528
|
||||
// Reference:
|
||||
// https://github.com/wpilibsuite/allwpilib/issues/8528
|
||||
if (g_gui_exit) {
|
||||
g_gui_exit();
|
||||
} else {
|
||||
@@ -41,4 +40,4 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ modification, are permitted provided that the following conditions are met:
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY ROBOTPY AND CONTRIBUTORS``AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROBOTPY OR CONTRIBUTORS BE LIABLE FOR
|
||||
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROBOTPY OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
@@ -45,12 +45,11 @@ Code for WPILib was derived from code using the following license:
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY FIRST AND CONTRIBUTORS``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
|
||||
* WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ classes:
|
||||
ColorOrder:
|
||||
inline_code: |
|
||||
.def("setData", [](wpi::AddressableLED& self, const wpi::AddressableLEDBuffer& data) {
|
||||
return self.SetData(data);
|
||||
return self.SetData(data);
|
||||
}, release_gil(), py::prepend());
|
||||
wpi::AddressableLED::LEDData:
|
||||
force_no_trampoline: true
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
namespace wpi::impl {
|
||||
void ResetSmartDashboardInstance();
|
||||
void ResetMotorSafety();
|
||||
} // namespace wpi::impl
|
||||
} // namespace wpi::impl
|
||||
|
||||
namespace wpi::util::impl {
|
||||
void ResetSendableRegistry();
|
||||
} // namespace wpi::impl
|
||||
} // namespace wpi::util::impl
|
||||
|
||||
void resetWpilibSimulationData() {
|
||||
wpi::impl::ResetSmartDashboardInstance();
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
#include "semiwrap_init.wpilib._wpilib.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) { initWrapper(m); }
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "rpy/AddressableLEDBuffer.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
@@ -21,17 +21,22 @@ void AddressableLEDBuffer::SetLED(size_t index, const wpi::util::Color& color) {
|
||||
m_buffer.at(index).SetLED(color);
|
||||
}
|
||||
|
||||
void AddressableLEDBuffer::SetLED(size_t index, const wpi::util::Color8Bit& color) {
|
||||
void AddressableLEDBuffer::SetLED(size_t index,
|
||||
const wpi::util::Color8Bit& color) {
|
||||
m_buffer.at(index).SetLED(color);
|
||||
}
|
||||
|
||||
int AddressableLEDBuffer::GetRed(size_t index) const { return m_buffer.at(index).r; }
|
||||
int AddressableLEDBuffer::GetRed(size_t index) const {
|
||||
return m_buffer.at(index).r;
|
||||
}
|
||||
|
||||
int AddressableLEDBuffer::GetGreen(size_t index) const {
|
||||
return m_buffer.at(index).g;
|
||||
}
|
||||
|
||||
int AddressableLEDBuffer::GetBlue(size_t index) const { return m_buffer.at(index).b; }
|
||||
int AddressableLEDBuffer::GetBlue(size_t index) const {
|
||||
return m_buffer.at(index).b;
|
||||
}
|
||||
|
||||
wpi::util::Color AddressableLEDBuffer::GetLED(size_t index) const {
|
||||
const auto& led = m_buffer.at(index);
|
||||
@@ -64,7 +69,8 @@ void AddressableLEDBuffer::View::SetHSV(size_t index, int h, int s, int v) {
|
||||
at(index).SetHSV(h, s, v);
|
||||
}
|
||||
|
||||
void AddressableLEDBuffer::View::SetLED(size_t index, const wpi::util::Color& color) {
|
||||
void AddressableLEDBuffer::View::SetLED(size_t index,
|
||||
const wpi::util::Color& color) {
|
||||
at(index).SetLED(color);
|
||||
}
|
||||
|
||||
@@ -81,8 +87,7 @@ AddressableLED::LEDData& AddressableLEDBuffer::View::at(size_t index) {
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
AddressableLED::LEDData& AddressableLEDBuffer::View::operator[](
|
||||
size_t index) {
|
||||
AddressableLED::LEDData& AddressableLEDBuffer::View::operator[](size_t index) {
|
||||
return at(index);
|
||||
}
|
||||
|
||||
@@ -105,7 +110,8 @@ wpi::util::Color AddressableLEDBuffer::View::GetLED(size_t index) const {
|
||||
return wpi::util::Color{led.r / 255.0, led.g / 255.0, led.b / 255.0};
|
||||
}
|
||||
|
||||
wpi::util::Color8Bit AddressableLEDBuffer::View::GetLED8Bit(size_t index) const {
|
||||
wpi::util::Color8Bit AddressableLEDBuffer::View::GetLED8Bit(
|
||||
size_t index) const {
|
||||
const auto& led = at(index);
|
||||
return wpi::util::Color8Bit{led.r, led.g, led.b};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "pybind11/pytypes.h"
|
||||
#include "wpi/hardware/led/AddressableLED.hpp"
|
||||
#include "wpi/util/Color.hpp"
|
||||
@@ -151,8 +152,9 @@ class AddressableLEDBuffer {
|
||||
auto end() { return m_buffer.end(); }
|
||||
|
||||
/**
|
||||
* A view of another addressable LED buffer. Views provide an easy way to split a large LED
|
||||
* strip into smaller sections that can be animated individually.
|
||||
* A view of another addressable LED buffer. Views provide an easy way to
|
||||
* split a large LED strip into smaller sections that can be animated
|
||||
* individually.
|
||||
*/
|
||||
class View {
|
||||
public:
|
||||
@@ -251,9 +253,7 @@ class AddressableLEDBuffer {
|
||||
/**
|
||||
* Implicit conversion to span of LED data
|
||||
*/
|
||||
operator std::span<wpi::AddressableLED::LEDData>() {
|
||||
return m_data;
|
||||
}
|
||||
operator std::span<wpi::AddressableLED::LEDData>() { return m_data; }
|
||||
|
||||
/**
|
||||
* Implicit conversion to span of const LED data
|
||||
@@ -272,7 +272,8 @@ class AddressableLEDBuffer {
|
||||
/**
|
||||
* Creates a read/write view of this buffer.
|
||||
*
|
||||
* @param slice the desired slice of the buffer (e.g. 2:4), step must be unspecified or 1
|
||||
* @param slice the desired slice of the buffer (e.g. 2:4), step must be
|
||||
* unspecified or 1
|
||||
* @return View object representing the view
|
||||
* @throws std::out_of_range if the view would exceed buffer bounds
|
||||
*/
|
||||
@@ -282,4 +283,4 @@ class AddressableLEDBuffer {
|
||||
std::vector<wpi::AddressableLED::LEDData> m_buffer;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
} // namespace wpi
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "wpi/util/fs.hpp"
|
||||
|
||||
namespace robotpy::filesystem {
|
||||
@@ -16,8 +18,8 @@ std::string GetOperatingDirectory();
|
||||
/**
|
||||
* Obtains the deploy directory of the program, which is the remote location
|
||||
* the deploy directory is deployed to by default. On the robot, this is
|
||||
* /home/systemcore/py/deploy. In simulation, it is where the simulation was launched
|
||||
* from, in the subdirectory "deploy" (`dirname(robot.py)`/deploy).
|
||||
* /home/systemcore/py/deploy. In simulation, it is where the simulation was
|
||||
* launched from, in the subdirectory "deploy" (`dirname(robot.py)`/deploy).
|
||||
*
|
||||
* @return The result of the operating directory lookup
|
||||
*/
|
||||
@@ -28,6 +30,6 @@ fs::path GetOperatingDirectoryFs();
|
||||
// intended to be used by C++ bindings, returns same as GetDeployDirectory
|
||||
fs::path GetDeployDirectoryFs();
|
||||
|
||||
} // namespace robotpy::filesystem
|
||||
} // namespace robotpy::filesystem
|
||||
|
||||
#include "Filesystem.inc"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
// TODO: this should be in a shared library, but robotpy-build does not support that
|
||||
// TODO: this should be in a shared library, but robotpy-build does not support
|
||||
// that
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <pybind11/eval.h>
|
||||
#include <semiwrap.h>
|
||||
@@ -42,13 +46,17 @@ inline std::string GetOperatingDirectory() {
|
||||
return GetOperatingDirectoryFs().string();
|
||||
}
|
||||
|
||||
inline std::string GetDeployDirectory() { return GetDeployDirectoryFs().string(); }
|
||||
inline std::string GetDeployDirectory() {
|
||||
return GetDeployDirectoryFs().string();
|
||||
}
|
||||
|
||||
inline fs::path GetOperatingDirectoryFs() {
|
||||
static fs::path operatingPath = getMainPath();
|
||||
return operatingPath;
|
||||
}
|
||||
|
||||
inline fs::path GetDeployDirectoryFs() { return GetOperatingDirectoryFs() / "deploy"; }
|
||||
inline fs::path GetDeployDirectoryFs() {
|
||||
return GetOperatingDirectoryFs() / "deploy";
|
||||
}
|
||||
|
||||
} // namespace robotpy::filesystem
|
||||
} // namespace robotpy::filesystem
|
||||
|
||||
@@ -40,7 +40,9 @@ void PyMotorControllerGroup::SetInverted(bool isInverted) {
|
||||
m_isInverted = isInverted;
|
||||
}
|
||||
|
||||
bool PyMotorControllerGroup::GetInverted() const { return m_isInverted; }
|
||||
bool PyMotorControllerGroup::GetInverted() const {
|
||||
return m_isInverted;
|
||||
}
|
||||
|
||||
void PyMotorControllerGroup::Disable() {
|
||||
for (auto motorController : m_motorControllers) {
|
||||
@@ -51,6 +53,7 @@ void PyMotorControllerGroup::Disable() {
|
||||
void PyMotorControllerGroup::InitSendable(wpi::util::SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Motor Controller");
|
||||
builder.SetActuator(true);
|
||||
builder.AddDoubleProperty("Value", [=, this]() { return GetThrottle(); },
|
||||
[=, this](double value) { SetThrottle(value); });
|
||||
builder.AddDoubleProperty(
|
||||
"Value", [=, this]() { return GetThrottle(); },
|
||||
[=, this](double value) { SetThrottle(value); });
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "wpi/hardware/motor/MotorController.hpp"
|
||||
#include "wpi/util/sendable/Sendable.hpp"
|
||||
@@ -15,12 +14,14 @@
|
||||
|
||||
namespace wpi {
|
||||
|
||||
class PyMotorControllerGroup : public wpi::util::Sendable,
|
||||
public MotorController,
|
||||
public wpi::util::SendableHelper<PyMotorControllerGroup> {
|
||||
class PyMotorControllerGroup
|
||||
: public wpi::util::Sendable,
|
||||
public MotorController,
|
||||
public wpi::util::SendableHelper<PyMotorControllerGroup> {
|
||||
public:
|
||||
PyMotorControllerGroup(std::vector<std::shared_ptr<wpi::MotorController>> &&args) :
|
||||
m_motorControllers(args) {}
|
||||
explicit PyMotorControllerGroup(
|
||||
std::vector<std::shared_ptr<wpi::MotorController>>&& args)
|
||||
: m_motorControllers(args) {}
|
||||
~PyMotorControllerGroup() override = default;
|
||||
|
||||
PyMotorControllerGroup(PyMotorControllerGroup&&) = default;
|
||||
@@ -42,4 +43,4 @@ class PyMotorControllerGroup : public wpi::util::Sendable,
|
||||
std::vector<std::shared_ptr<wpi::MotorController>> m_motorControllers;
|
||||
};
|
||||
|
||||
} // namespace rpy
|
||||
} // namespace wpi
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <gilsafe_object.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "wpi/hal/Notifier.hpp"
|
||||
#include "wpi/hal/Threads.h"
|
||||
#include "wpi/system/Errors.hpp"
|
||||
#include "wpi/system/Timer.hpp"
|
||||
#include "wpi/util/Synchronization.h"
|
||||
|
||||
#include <pybind11/functional.h>
|
||||
#include <gilsafe_object.h>
|
||||
|
||||
using namespace wpi;
|
||||
using namespace pybind11::literals;
|
||||
|
||||
@@ -100,14 +100,14 @@ PyNotifier::~PyNotifier() {
|
||||
}
|
||||
}
|
||||
|
||||
PyNotifier::PyNotifier(PyNotifier &&rhs)
|
||||
PyNotifier::PyNotifier(PyNotifier&& rhs)
|
||||
: m_thread(std::move(rhs.m_thread)),
|
||||
m_notifier(rhs.m_notifier.load()),
|
||||
m_handler(std::move(rhs.m_handler)) {
|
||||
rhs.m_notifier = HAL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
PyNotifier &PyNotifier::operator=(PyNotifier &&rhs) {
|
||||
PyNotifier& PyNotifier::operator=(PyNotifier&& rhs) {
|
||||
m_thread = std::move(rhs.m_thread);
|
||||
m_notifier = rhs.m_notifier.load();
|
||||
rhs.m_notifier = HAL_INVALID_HANDLE;
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/hal/Types.h"
|
||||
#include "wpi/units/time.hpp"
|
||||
#include "wpi/util/mutex.hpp"
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
namespace wpi {
|
||||
|
||||
class PyNotifier {
|
||||
@@ -42,8 +42,8 @@ class PyNotifier {
|
||||
*/
|
||||
virtual ~PyNotifier();
|
||||
|
||||
PyNotifier(PyNotifier &&rhs);
|
||||
PyNotifier &operator=(PyNotifier &&rhs);
|
||||
PyNotifier(PyNotifier&& rhs);
|
||||
PyNotifier& operator=(PyNotifier&& rhs);
|
||||
|
||||
/**
|
||||
* Sets the name of the notifier. Used for debugging purposes only.
|
||||
@@ -101,7 +101,7 @@ class PyNotifier {
|
||||
*/
|
||||
int32_t GetOverrun() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
// The thread waiting on the HAL alarm
|
||||
py::object m_thread;
|
||||
|
||||
@@ -115,4 +115,4 @@ private:
|
||||
std::function<void()> m_handler;
|
||||
};
|
||||
|
||||
} // namespace wpi
|
||||
} // namespace wpi
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
#include "SmartDashboardData.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace rpy {
|
||||
|
||||
//
|
||||
@@ -10,25 +12,26 @@ namespace rpy {
|
||||
// All functions here must be called with the GIL held
|
||||
//
|
||||
|
||||
static py::dict &getSmartDashboardData() {
|
||||
static py::dict& getSmartDashboardData() {
|
||||
static py::dict data;
|
||||
return data;
|
||||
}
|
||||
|
||||
void addSmartDashboardData(py::str &key, std::shared_ptr<wpi::util::Sendable> data) {
|
||||
auto &sdData = getSmartDashboardData();
|
||||
void addSmartDashboardData(py::str& key,
|
||||
std::shared_ptr<wpi::util::Sendable> data) {
|
||||
auto& sdData = getSmartDashboardData();
|
||||
sdData[key] = py::cast(data);
|
||||
}
|
||||
|
||||
void clearSmartDashboardData() {
|
||||
auto &sdData = getSmartDashboardData();
|
||||
auto& sdData = getSmartDashboardData();
|
||||
if (sdData) {
|
||||
sdData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void destroySmartDashboardData() {
|
||||
auto &sdData = getSmartDashboardData();
|
||||
auto& sdData = getSmartDashboardData();
|
||||
if (sdData) {
|
||||
sdData.clear();
|
||||
// force the dictionary to be deleted otherwise it'll crash when libc++
|
||||
@@ -40,4 +43,4 @@ void destroySmartDashboardData() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rpy
|
||||
} // namespace rpy
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wpi/util/sendable/Sendable.hpp"
|
||||
#include <memory>
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/util/sendable/Sendable.hpp"
|
||||
|
||||
namespace rpy {
|
||||
|
||||
//
|
||||
// These functions must be called with the GIL held
|
||||
//
|
||||
|
||||
void addSmartDashboardData(py::str &key, std::shared_ptr<wpi::util::Sendable> data);
|
||||
void addSmartDashboardData(py::str& key,
|
||||
std::shared_ptr<wpi::util::Sendable> data);
|
||||
void clearSmartDashboardData();
|
||||
void destroySmartDashboardData();
|
||||
|
||||
} // namespace rpy
|
||||
} // namespace rpy
|
||||
|
||||
@@ -43,7 +43,7 @@ inline_code: |
|
||||
self->ax = ax;
|
||||
}
|
||||
)
|
||||
.def_property("ay_fpss",
|
||||
.def_property("ay_fpss",
|
||||
[](ChassisAccelerations * self) -> wpi::units::feet_per_second_squared_t {
|
||||
return self->ay;
|
||||
},
|
||||
@@ -51,7 +51,7 @@ inline_code: |
|
||||
self->ay = ay;
|
||||
}
|
||||
)
|
||||
.def_property("alpha_dpss",
|
||||
.def_property("alpha_dpss",
|
||||
[](ChassisAccelerations * self) -> wpi::units::degrees_per_second_squared_t {
|
||||
return self->alpha;
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ inline_code: |
|
||||
self->vx = vx;
|
||||
}
|
||||
)
|
||||
.def_property("vy_fps",
|
||||
.def_property("vy_fps",
|
||||
[](ChassisVelocities * self) -> wpi::units::feet_per_second_t {
|
||||
return self->vy;
|
||||
},
|
||||
@@ -53,7 +53,7 @@ inline_code: |
|
||||
self->vy = vy;
|
||||
}
|
||||
)
|
||||
.def_property("omega_dps",
|
||||
.def_property("omega_dps",
|
||||
[](ChassisVelocities * self) -> wpi::units::degrees_per_second_t {
|
||||
return self->omega;
|
||||
},
|
||||
|
||||
@@ -36,7 +36,7 @@ inline_code: |
|
||||
self->left = left;
|
||||
}
|
||||
)
|
||||
.def_property("right_fpss",
|
||||
.def_property("right_fpss",
|
||||
[](DifferentialDriveWheelAccelerations * self) -> wpi::units::feet_per_second_squared_t {
|
||||
return self->right;
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@ inline_code: |
|
||||
self->left = left;
|
||||
}
|
||||
)
|
||||
.def_property("right_fps",
|
||||
.def_property("right_fps",
|
||||
[](DifferentialDriveWheelVelocities * self) -> wpi::units::feet_per_second_t {
|
||||
return self->right;
|
||||
},
|
||||
@@ -50,4 +50,3 @@ inline_code: |
|
||||
;
|
||||
|
||||
SetupWPyStruct<wpi::math::DifferentialDriveWheelVelocities>(cls_DifferentialDriveWheelVelocities);
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ inline_code: |
|
||||
>(),
|
||||
py::arg("frontLeft") = 0, py::arg("frontRight") = 0, py::arg("rearLeft") = 0, py::arg("rearRight") = 0
|
||||
)
|
||||
.def_static("fromFps", [](wpi::units::feet_per_second_squared_t frontLeft,
|
||||
wpi::units::feet_per_second_squared_t frontRight,
|
||||
wpi::units::feet_per_second_squared_t rearLeft,
|
||||
.def_static("fromFps", [](wpi::units::feet_per_second_squared_t frontLeft,
|
||||
wpi::units::feet_per_second_squared_t frontRight,
|
||||
wpi::units::feet_per_second_squared_t rearLeft,
|
||||
wpi::units::feet_per_second_squared_t rearRight){
|
||||
return MecanumDriveWheelAccelerations{frontLeft, frontRight, rearLeft, rearRight};
|
||||
}, py::arg("frontLeft") = 0, py::arg("frontRight") = 0, py::arg("rearLeft") = 0, py::arg("rearRight") = 0)
|
||||
@@ -43,7 +43,7 @@ inline_code: |
|
||||
self->frontLeft = frontLeft;
|
||||
}
|
||||
)
|
||||
.def_property("front_right_fpss",
|
||||
.def_property("front_right_fpss",
|
||||
[](MecanumDriveWheelAccelerations * self) -> wpi::units::feet_per_second_squared_t {
|
||||
return self->frontRight;
|
||||
},
|
||||
@@ -59,7 +59,7 @@ inline_code: |
|
||||
self->rearLeft = rearLeft;
|
||||
}
|
||||
)
|
||||
.def_property("rear_right_fpss",
|
||||
.def_property("rear_right_fpss",
|
||||
[](MecanumDriveWheelAccelerations * self) -> wpi::units::feet_per_second_squared_t {
|
||||
return self->rearRight;
|
||||
},
|
||||
|
||||
@@ -46,7 +46,7 @@ inline_code: |
|
||||
self->frontLeft = fps;
|
||||
}
|
||||
)
|
||||
.def_property("frontRight_fps",
|
||||
.def_property("frontRight_fps",
|
||||
[](MecanumDriveWheelVelocities * self) -> wpi::units::feet_per_second_t {
|
||||
return self->frontRight;
|
||||
},
|
||||
@@ -62,7 +62,7 @@ inline_code: |
|
||||
self->rearLeft = fps;
|
||||
}
|
||||
)
|
||||
.def_property("rearRight_fps",
|
||||
.def_property("rearRight_fps",
|
||||
[](MecanumDriveWheelVelocities * self) -> wpi::units::feet_per_second_t {
|
||||
return self->rearRight;
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@ inline_code: |-
|
||||
"\n"
|
||||
":param kinematics: The swerve drive kinematics.")
|
||||
)
|
||||
|
||||
|
||||
.def("setKinematics", static_cast<void (wpi::math::TrajectoryConfig::*)(wpi::math::SwerveDriveKinematics<3>&)>(
|
||||
&wpi::math::TrajectoryConfig::SetKinematics<3>),
|
||||
py::arg("kinematics"), release_gil(), py::doc(
|
||||
@@ -50,7 +50,7 @@ inline_code: |-
|
||||
"\n"
|
||||
":param kinematics: The swerve drive kinematics.")
|
||||
)
|
||||
|
||||
|
||||
.def("setKinematics", static_cast<void (wpi::math::TrajectoryConfig::*)(wpi::math::SwerveDriveKinematics<4>&)>(
|
||||
&wpi::math::TrajectoryConfig::SetKinematics<4>),
|
||||
py::arg("kinematics"), release_gil(), py::doc(
|
||||
@@ -59,7 +59,7 @@ inline_code: |-
|
||||
"\n"
|
||||
":param kinematics: The swerve drive kinematics.")
|
||||
)
|
||||
|
||||
|
||||
.def("setKinematics", static_cast<void (wpi::math::TrajectoryConfig::*)(wpi::math::SwerveDriveKinematics<6>&)>(
|
||||
&wpi::math::TrajectoryConfig::SetKinematics<6>),
|
||||
py::arg("kinematics"), release_gil(), py::doc(
|
||||
|
||||
@@ -19,4 +19,3 @@ classes:
|
||||
- [CubicHermiteSpline]
|
||||
- [QuinticHermiteSpline]
|
||||
SetErrorHandler:
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ inline_code: |
|
||||
.def_static("fromFeet", [](wpi::units::foot_t dx, wpi::units::foot_t dy, wpi::units::radian_t dtheta){
|
||||
return Twist2d{dx, dy, dtheta};
|
||||
}, py::arg("dx") = 0, py::arg("dy") = 0, py::arg("dtheta") = 0)
|
||||
.def_property("dx_feet",
|
||||
.def_property("dx_feet",
|
||||
[](Twist2d * self) -> wpi::units::foot_t {
|
||||
return self->dx;
|
||||
},
|
||||
@@ -30,7 +30,7 @@ inline_code: |
|
||||
self->dx = dx;
|
||||
}
|
||||
)
|
||||
.def_property("dy_feet",
|
||||
.def_property("dy_feet",
|
||||
[](Twist2d * self) -> wpi::units::foot_t {
|
||||
return self->dy;
|
||||
},
|
||||
@@ -38,7 +38,7 @@ inline_code: |
|
||||
self->dy = dy;
|
||||
}
|
||||
)
|
||||
.def_property("dtheta_degrees",
|
||||
.def_property("dtheta_degrees",
|
||||
[](Twist2d * self) -> wpi::units::degree_t {
|
||||
return self->dtheta;
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@ inline_code: |-
|
||||
},
|
||||
py::arg("dx") = 0, py::arg("dy") = 0, py::arg("dz") = 0,
|
||||
py::arg("rx") = 0, py::arg("ry") = 0, py::arg("rz") = 0)
|
||||
.def_property("dx_feet",
|
||||
.def_property("dx_feet",
|
||||
[](Twist3d * self) -> wpi::units::foot_t {
|
||||
return self->dx;
|
||||
},
|
||||
@@ -38,7 +38,7 @@ inline_code: |-
|
||||
self->dx = dx;
|
||||
}
|
||||
)
|
||||
.def_property("dy_feet",
|
||||
.def_property("dy_feet",
|
||||
[](Twist3d * self) -> wpi::units::foot_t {
|
||||
return self->dy;
|
||||
},
|
||||
@@ -46,7 +46,7 @@ inline_code: |-
|
||||
self->dy = dy;
|
||||
}
|
||||
)
|
||||
.def_property("dz_feet",
|
||||
.def_property("dz_feet",
|
||||
[](Twist3d * self) -> wpi::units::foot_t {
|
||||
return self->dz;
|
||||
},
|
||||
@@ -54,7 +54,7 @@ inline_code: |-
|
||||
self->dz = dz;
|
||||
}
|
||||
)
|
||||
.def_property("rx_degrees",
|
||||
.def_property("rx_degrees",
|
||||
[](Twist3d * self) -> wpi::units::degree_t {
|
||||
return self->rx;
|
||||
},
|
||||
@@ -62,7 +62,7 @@ inline_code: |-
|
||||
self->rx = rx;
|
||||
}
|
||||
)
|
||||
.def_property("ry_degrees",
|
||||
.def_property("ry_degrees",
|
||||
[](Twist3d * self) -> wpi::units::degree_t {
|
||||
return self->ry;
|
||||
},
|
||||
@@ -70,7 +70,7 @@ inline_code: |-
|
||||
self->ry = ry;
|
||||
}
|
||||
)
|
||||
.def_property("rz_degrees",
|
||||
.def_property("rz_degrees",
|
||||
[](Twist3d * self) -> wpi::units::degree_t {
|
||||
return self->rz;
|
||||
},
|
||||
|
||||
@@ -1,37 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "wpi/math/trajectory/constraint/TrajectoryConstraint.hpp"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/math/trajectory/constraint/TrajectoryConstraint.hpp"
|
||||
|
||||
namespace wpi::math {
|
||||
|
||||
struct PyTrajectoryConstraint : public TrajectoryConstraint {
|
||||
|
||||
PyTrajectoryConstraint() {}
|
||||
|
||||
wpi::units::meters_per_second_t
|
||||
MaxVelocity(const Pose2d &pose, wpi::units::curvature_t curvature,
|
||||
wpi::units::meters_per_second_t velocity) const override {
|
||||
wpi::units::meters_per_second_t MaxVelocity(
|
||||
const Pose2d& pose, wpi::units::curvature_t curvature,
|
||||
wpi::units::meters_per_second_t velocity) const override {
|
||||
return m_constraint->MaxVelocity(pose, curvature, velocity);
|
||||
}
|
||||
|
||||
MinMax MinMaxAcceleration(const Pose2d &pose, wpi::units::curvature_t curvature,
|
||||
wpi::units::meters_per_second_t velocity) const override {
|
||||
MinMax MinMaxAcceleration(
|
||||
const Pose2d& pose, wpi::units::curvature_t curvature,
|
||||
wpi::units::meters_per_second_t velocity) const override {
|
||||
return m_constraint->MinMaxAcceleration(pose, curvature, velocity);
|
||||
}
|
||||
|
||||
std::shared_ptr<TrajectoryConstraint> m_constraint;
|
||||
};
|
||||
|
||||
}; // namespace wpi::math
|
||||
}; // namespace wpi::math
|
||||
|
||||
namespace pybind11 {
|
||||
namespace detail {
|
||||
namespace pybind11::detail {
|
||||
|
||||
template <> struct type_caster<wpi::math::PyTrajectoryConstraint> {
|
||||
using value_conv = make_caster<std::shared_ptr<wpi::math::TrajectoryConstraint>>;
|
||||
template <>
|
||||
struct type_caster<wpi::math::PyTrajectoryConstraint> {
|
||||
using value_conv =
|
||||
make_caster<std::shared_ptr<wpi::math::TrajectoryConstraint>>;
|
||||
|
||||
PYBIND11_TYPE_CASTER(wpi::math::PyTrajectoryConstraint, _("wpimath._wpimath.TrajectoryConstraint"));
|
||||
PYBIND11_TYPE_CASTER(wpi::math::PyTrajectoryConstraint,
|
||||
_("wpimath._wpimath.TrajectoryConstraint"));
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
value_conv conv;
|
||||
@@ -40,15 +46,15 @@ template <> struct type_caster<wpi::math::PyTrajectoryConstraint> {
|
||||
}
|
||||
|
||||
value.m_constraint =
|
||||
cast_op<std::shared_ptr<wpi::math::TrajectoryConstraint>>(std::move(conv));
|
||||
cast_op<std::shared_ptr<wpi::math::TrajectoryConstraint>>(
|
||||
std::move(conv));
|
||||
return true;
|
||||
}
|
||||
|
||||
static handle cast(const wpi::math::PyTrajectoryConstraint &src,
|
||||
static handle cast(const wpi::math::PyTrajectoryConstraint& src,
|
||||
return_value_policy policy, handle parent) {
|
||||
return value_conv::cast(src.m_constraint, policy, parent);
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace detail
|
||||
}; // namespace pybind11
|
||||
} // namespace pybind11::detail
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "wpi/math/geometry/Ellipse2d.hpp"
|
||||
@@ -11,11 +13,11 @@
|
||||
|
||||
namespace rpy {
|
||||
|
||||
inline std::string toString(const wpi::math::Rotation2d &self) {
|
||||
inline std::string toString(const wpi::math::Rotation2d& self) {
|
||||
return "Rotation2d(" + std::to_string(self.Radians()()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Rotation3d &self) {
|
||||
inline std::string toString(const wpi::math::Rotation3d& self) {
|
||||
return "Rotation3d("
|
||||
"x=" +
|
||||
std::to_string(self.X()()) +
|
||||
@@ -27,7 +29,7 @@ inline std::string toString(const wpi::math::Rotation3d &self) {
|
||||
std::to_string(self.Z()()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Translation2d &self) {
|
||||
inline std::string toString(const wpi::math::Translation2d& self) {
|
||||
return "Translation2d("
|
||||
"x=" +
|
||||
std::to_string(self.X()()) +
|
||||
@@ -36,7 +38,7 @@ inline std::string toString(const wpi::math::Translation2d &self) {
|
||||
std::to_string(self.Y()()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Translation3d &self) {
|
||||
inline std::string toString(const wpi::math::Translation3d& self) {
|
||||
return "Translation3d("
|
||||
"x=" +
|
||||
std::to_string(self.X()()) +
|
||||
@@ -48,7 +50,7 @@ inline std::string toString(const wpi::math::Translation3d &self) {
|
||||
std::to_string(self.Z()()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Quaternion &self) {
|
||||
inline std::string toString(const wpi::math::Quaternion& self) {
|
||||
return "Quaternion("
|
||||
"w=" +
|
||||
std::to_string(self.W()) +
|
||||
@@ -63,37 +65,36 @@ inline std::string toString(const wpi::math::Quaternion &self) {
|
||||
std::to_string(self.Z()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Transform2d &self) {
|
||||
inline std::string toString(const wpi::math::Transform2d& self) {
|
||||
return "Transform2d(" + rpy::toString(self.Translation()) + ", " +
|
||||
rpy::toString(self.Rotation()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Transform3d &self) {
|
||||
inline std::string toString(const wpi::math::Transform3d& self) {
|
||||
return "Transform3d(" + rpy::toString(self.Translation()) + ", " +
|
||||
rpy::toString(self.Rotation()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Pose2d &self) {
|
||||
inline std::string toString(const wpi::math::Pose2d& self) {
|
||||
return "Pose2d(" + rpy::toString(self.Translation()) + ", " +
|
||||
rpy::toString(self.Rotation()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Pose3d &self) {
|
||||
inline std::string toString(const wpi::math::Pose3d& self) {
|
||||
return "Pose3d(" + rpy::toString(self.Translation()) + ", " +
|
||||
rpy::toString(self.Rotation()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Rectangle2d &self) {
|
||||
inline std::string toString(const wpi::math::Rectangle2d& self) {
|
||||
return "Rectangle2d(center=" + rpy::toString(self.Center()) +
|
||||
", xWidth=" + std::to_string(self.XWidth()()) +
|
||||
", yWidth=" + std::to_string(self.YWidth()()) + ")";
|
||||
", xWidth=" + std::to_string(self.XWidth()()) +
|
||||
", yWidth=" + std::to_string(self.YWidth()()) + ")";
|
||||
}
|
||||
|
||||
inline std::string toString(const wpi::math::Ellipse2d &self) {
|
||||
inline std::string toString(const wpi::math::Ellipse2d& self) {
|
||||
return "Ellipse2d(center=" + rpy::toString(self.Center()) +
|
||||
", xSemiAxis=" + std::to_string(self.XSemiAxis()()) +
|
||||
", ySemiAxis=" + std::to_string(self.YSemiAxis()()) + ")";
|
||||
", xSemiAxis=" + std::to_string(self.XSemiAxis()()) +
|
||||
", ySemiAxis=" + std::to_string(self.YSemiAxis()()) + ")";
|
||||
}
|
||||
|
||||
|
||||
} // namespace rpy
|
||||
} // namespace rpy
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
#include "semiwrap_init.wpimath._wpimath.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) { initWrapper(m); }
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wpi/units/time.hpp"
|
||||
#include "wpi/units/length.hpp"
|
||||
#include "wpi/units/time.hpp"
|
||||
|
||||
struct SomeClass {
|
||||
static constexpr auto s_constant = 2_s;
|
||||
static constexpr auto ms_constant1 = 20_ms;
|
||||
static constexpr wpi::units::second_t ms_constant2 = 50_ms;
|
||||
static constexpr wpi::units::millisecond_t ms_constant3 = 0.20_s;
|
||||
static constexpr auto s_constant = 2_s;
|
||||
static constexpr auto ms_constant1 = 20_ms;
|
||||
static constexpr wpi::units::second_t ms_constant2 = 50_ms;
|
||||
static constexpr wpi::units::millisecond_t ms_constant3 = 0.20_s;
|
||||
|
||||
bool checkDefaultByName1(wpi::units::second_t period = ms_constant1);
|
||||
bool checkDefaultByName2(wpi::units::second_t period = ms_constant2);
|
||||
bool checkDefaultByNum1(wpi::units::second_t period = 50_ms);
|
||||
bool checkDefaultByNum2(wpi::units::second_t period = 0.5_s);
|
||||
bool checkDefaultByName1(wpi::units::second_t period = ms_constant1);
|
||||
bool checkDefaultByName2(wpi::units::second_t period = ms_constant2);
|
||||
bool checkDefaultByNum1(wpi::units::second_t period = 50_ms);
|
||||
bool checkDefaultByNum2(wpi::units::second_t period = 0.5_s);
|
||||
|
||||
wpi::units::second_t ms2s(wpi::units::millisecond_t ms);
|
||||
wpi::units::millisecond_t s2ms(wpi::units::second_t s);
|
||||
wpi::units::second_t ms2s(wpi::units::millisecond_t ms);
|
||||
wpi::units::millisecond_t s2ms(wpi::units::second_t s);
|
||||
|
||||
static constexpr wpi::units::foot_t five_ft = 5_ft;
|
||||
static constexpr wpi::units::foot_t five_ft = 5_ft;
|
||||
|
||||
wpi::units::meter_t ft2m(wpi::units::foot_t f);
|
||||
};
|
||||
wpi::units::meter_t ft2m(wpi::units::foot_t f);
|
||||
};
|
||||
|
||||
@@ -1,53 +1,50 @@
|
||||
|
||||
#include "semiwrap_init.wpimath_test._wpimath_test.hpp"
|
||||
#include <module.h>
|
||||
#include <stdexcept>
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m)
|
||||
{
|
||||
initWrapper(m);
|
||||
#include <module.h>
|
||||
|
||||
#include "semiwrap_init.wpimath_test._wpimath_test.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
bool SomeClass::checkDefaultByName1(wpi::units::second_t period)
|
||||
{
|
||||
if (period != SomeClass::ms_constant1) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
bool SomeClass::checkDefaultByName1(wpi::units::second_t period) {
|
||||
if (period != SomeClass::ms_constant1) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SomeClass::checkDefaultByName2(wpi::units::second_t period)
|
||||
{
|
||||
if (period != SomeClass::ms_constant2) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
bool SomeClass::checkDefaultByName2(wpi::units::second_t period) {
|
||||
if (period != SomeClass::ms_constant2) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SomeClass::checkDefaultByNum1(wpi::units::second_t period)
|
||||
{
|
||||
if (period != 50_ms) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
bool SomeClass::checkDefaultByNum1(wpi::units::second_t period) {
|
||||
if (period != 50_ms) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SomeClass::checkDefaultByNum2(wpi::units::second_t period)
|
||||
{
|
||||
if (period != 50_ms) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
bool SomeClass::checkDefaultByNum2(wpi::units::second_t period) {
|
||||
if (period != 50_ms) {
|
||||
throw std::runtime_error(wpi::units::to_string(period));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
wpi::units::meter_t SomeClass::ft2m(wpi::units::foot_t f) {
|
||||
return f;
|
||||
return f;
|
||||
}
|
||||
|
||||
wpi::units::second_t SomeClass::ms2s(wpi::units::millisecond_t ms) {
|
||||
return ms;
|
||||
return ms;
|
||||
}
|
||||
|
||||
wpi::units::millisecond_t SomeClass::s2ms(wpi::units::second_t s) {
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
#include <semiwrap_init.wpinet._wpinet.hpp>
|
||||
#include "semiwrap_init.wpinet._wpinet.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) { initWrapper(m); }
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
defaults:
|
||||
ignore: true
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#include <semiwrap_init.wpiutil._wpiutil.hpp>
|
||||
#include "semiwrap_init.wpiutil._wpiutil.hpp"
|
||||
|
||||
void setup_stack_trace_hook(py::object fn);
|
||||
void cleanup_stack_trace_hook();
|
||||
@@ -14,7 +14,7 @@ void cleanup_now_impl();
|
||||
|
||||
namespace wpi::util::impl {
|
||||
void ResetSendableRegistry();
|
||||
} // namespace wpi::util::impl
|
||||
} // namespace wpi::util::impl
|
||||
|
||||
void cleanup_sendable_registry() {
|
||||
py::gil_scoped_release unlock;
|
||||
@@ -31,7 +31,7 @@ SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
|
||||
static int unused;
|
||||
py::capsule cleanup(&unused, [](void *) {
|
||||
py::capsule cleanup(&unused, [](void*) {
|
||||
cleanup_sendable_registry();
|
||||
cleanup_stack_trace_hook();
|
||||
cleanup_safethread_gil();
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <gilsafe_object.h>
|
||||
#include <semiwrap.h>
|
||||
|
||||
using OnThreadStartFn = void *(*)();
|
||||
using OnThreadEndFn = void (*)(void *);
|
||||
using OnThreadStartFn = void* (*)();
|
||||
using OnThreadEndFn = void (*)(void*);
|
||||
|
||||
namespace wpi::util::impl {
|
||||
void SetSafeThreadNotifiers(OnThreadStartFn OnStart, OnThreadEndFn OnEnd);
|
||||
}
|
||||
|
||||
struct SafeThreadState {
|
||||
py::gil_scoped_acquire *acquire = nullptr;
|
||||
py::gil_scoped_release *release = nullptr;
|
||||
py::gil_scoped_acquire* acquire = nullptr;
|
||||
py::gil_scoped_release* release = nullptr;
|
||||
};
|
||||
|
||||
std::atomic<bool> g_gilstate_managed = false;
|
||||
|
||||
void *on_safe_thread_start() {
|
||||
if (Py_IsFinalizing() // python is shutting down
|
||||
|| !g_gilstate_managed.load() // python has shutdown)
|
||||
void* on_safe_thread_start() {
|
||||
if (Py_IsFinalizing() // python is shutting down
|
||||
|| !g_gilstate_managed.load() // python has shutdown)
|
||||
) {
|
||||
return nullptr;
|
||||
}
|
||||
auto *st = new SafeThreadState;
|
||||
auto* st = new SafeThreadState;
|
||||
|
||||
// acquires the GIL and creates pybind11's thread state for this thread
|
||||
st->acquire = new py::gil_scoped_acquire;
|
||||
@@ -33,20 +34,20 @@ void *on_safe_thread_start() {
|
||||
return st;
|
||||
}
|
||||
|
||||
void on_safe_thread_end(void *opaque) {
|
||||
void on_safe_thread_end(void* opaque) {
|
||||
// on entry, GIL should not be acquired
|
||||
|
||||
// don't cleanup if it's unsafe to do so. Several possibilities here:
|
||||
if (!opaque // internal error?
|
||||
|| Py_IsFinalizing() // python is shutting down
|
||||
|| !g_gilstate_managed.load() // python has shutdown
|
||||
if (!opaque // internal error?
|
||||
|| Py_IsFinalizing() // python is shutting down
|
||||
|| !g_gilstate_managed.load() // python has shutdown
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *st = (SafeThreadState *)opaque;
|
||||
delete st->release; // causes GIL to be acquired
|
||||
delete st->acquire; // causes GIL to be released and thread state deleted
|
||||
auto* st = reinterpret_cast<SafeThreadState*>(opaque);
|
||||
delete st->release; // causes GIL to be acquired
|
||||
delete st->acquire; // causes GIL to be released and thread state deleted
|
||||
delete st;
|
||||
}
|
||||
|
||||
@@ -59,7 +60,10 @@ void setup_safethread_gil() {
|
||||
atexit.attr("register")(
|
||||
py::cpp_function([]() { g_gilstate_managed = false; }));
|
||||
|
||||
wpi::util::impl::SetSafeThreadNotifiers(on_safe_thread_start, on_safe_thread_end);
|
||||
wpi::util::impl::SetSafeThreadNotifiers(on_safe_thread_start,
|
||||
on_safe_thread_end);
|
||||
}
|
||||
|
||||
void cleanup_safethread_gil() { g_gilstate_managed = false; }
|
||||
void cleanup_safethread_gil() {
|
||||
g_gilstate_managed = false;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/util/StackTrace.hpp"
|
||||
|
||||
py::object &get_hook_ref() {
|
||||
py::object& get_hook_ref() {
|
||||
static py::object hook;
|
||||
return hook;
|
||||
}
|
||||
|
||||
std::string final_py_stack_trace_hook(int offset) {
|
||||
std::string msg = "\tat <python stack trace not available due to interpreter shutdown>\n";
|
||||
std::string msg =
|
||||
"\tat <python stack trace not available due to interpreter shutdown>\n";
|
||||
msg += wpi::util::GetStackTraceDefault(offset);
|
||||
return msg;
|
||||
}
|
||||
@@ -17,11 +21,11 @@ std::string py_stack_trace_hook(int offset) {
|
||||
py::gil_scoped_acquire gil;
|
||||
|
||||
try {
|
||||
auto &hook = get_hook_ref();
|
||||
auto& hook = get_hook_ref();
|
||||
if (hook) {
|
||||
return py::cast<std::string>(hook(offset));
|
||||
}
|
||||
} catch (py::error_already_set &e) {
|
||||
} catch (py::error_already_set& e) {
|
||||
e.discard_as_unraisable("wpiutil._stacktrace._stack_trace_hook");
|
||||
}
|
||||
|
||||
@@ -37,9 +41,9 @@ void cleanup_stack_trace_hook() {
|
||||
wpi::util::SetGetStackTraceImpl(final_py_stack_trace_hook);
|
||||
|
||||
// release the function during interpreter shutdown
|
||||
auto &hook = get_hook_ref();
|
||||
auto& hook = get_hook_ref();
|
||||
if (hook) {
|
||||
hook.dec_ref();
|
||||
hook.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "wpi/util/timestamp.hpp"
|
||||
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
py::object &get_now_impl_ref() {
|
||||
py::object& get_now_impl_ref() {
|
||||
static py::object get_now_impl_ref;
|
||||
return get_now_impl_ref;
|
||||
}
|
||||
@@ -14,11 +14,11 @@ py::object &get_now_impl_ref() {
|
||||
uint64_t now_impl_trampoline() {
|
||||
py::gil_scoped_acquire acquire;
|
||||
try {
|
||||
auto &hook = get_now_impl_ref();
|
||||
auto& hook = get_now_impl_ref();
|
||||
if (hook) {
|
||||
return hook().cast<uint64_t>();
|
||||
}
|
||||
} catch (py::error_already_set &e) {
|
||||
} catch (py::error_already_set& e) {
|
||||
e.discard_as_unraisable("wpiutil.now_impl_trampoline");
|
||||
}
|
||||
|
||||
@@ -26,21 +26,21 @@ uint64_t now_impl_trampoline() {
|
||||
}
|
||||
|
||||
void set_now_impl(py::object func) {
|
||||
get_now_impl_ref() = func;
|
||||
if (func.is_none()) {
|
||||
wpi::util::SetNowImpl(nullptr);
|
||||
} else {
|
||||
wpi::util::SetNowImpl(&now_impl_trampoline);
|
||||
}
|
||||
get_now_impl_ref() = func;
|
||||
if (func.is_none()) {
|
||||
wpi::util::SetNowImpl(nullptr);
|
||||
} else {
|
||||
wpi::util::SetNowImpl(&now_impl_trampoline);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_now_impl() {
|
||||
wpi::util::SetNowImpl(nullptr);
|
||||
|
||||
// release the function during interpreter shutdown
|
||||
auto &hook = get_now_impl_ref();
|
||||
auto& hook = get_now_impl_ref();
|
||||
if (hook) {
|
||||
hook.dec_ref();
|
||||
hook.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include "wpi/util/struct/Struct.hpp"
|
||||
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/typing.h>
|
||||
#include <semiwrap.h>
|
||||
|
||||
static inline std::string pytypename(const py::type &t) {
|
||||
return ((PyTypeObject *)t.ptr())->tp_name;
|
||||
#include "wpi/util/struct/Struct.hpp"
|
||||
|
||||
static inline std::string pytypename(const py::type& t) {
|
||||
return (reinterpret_cast<PyTypeObject*>(t.ptr()))->tp_name;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -23,15 +24,14 @@ static inline std::string pytypename(const py::type &t) {
|
||||
// This merely holds the python object being operated on, the actual
|
||||
// serialization work is done in WPyStructConverter
|
||||
struct WPyStruct {
|
||||
|
||||
WPyStruct() = default;
|
||||
|
||||
WPyStruct(const WPyStruct &other) {
|
||||
WPyStruct(const WPyStruct& other) {
|
||||
py::gil_scoped_acquire gil;
|
||||
py = other.py;
|
||||
}
|
||||
|
||||
WPyStruct &operator=(const WPyStruct &other) {
|
||||
WPyStruct& operator=(const WPyStruct& other) {
|
||||
{
|
||||
py::gil_scoped_acquire gil;
|
||||
py = other.py;
|
||||
@@ -39,9 +39,9 @@ struct WPyStruct {
|
||||
return *this;
|
||||
}
|
||||
|
||||
WPyStruct(WPyStruct &&) = default;
|
||||
WPyStruct(WPyStruct&&) = default;
|
||||
|
||||
WPyStruct(const py::object &py) : py(py) {}
|
||||
explicit WPyStruct(const py::object& py) : py(py) {}
|
||||
|
||||
~WPyStruct() {
|
||||
py::gil_scoped_acquire gil;
|
||||
@@ -51,10 +51,10 @@ struct WPyStruct {
|
||||
py::object py;
|
||||
};
|
||||
|
||||
namespace pybind11 {
|
||||
namespace detail {
|
||||
namespace pybind11::detail {
|
||||
|
||||
template <> struct type_caster<WPyStruct> {
|
||||
template <>
|
||||
struct type_caster<WPyStruct> {
|
||||
// TODO: wpiutil.struct.T/TV?
|
||||
PYBIND11_TYPE_CASTER(WPyStruct, const_name("object"));
|
||||
|
||||
@@ -64,7 +64,7 @@ template <> struct type_caster<WPyStruct> {
|
||||
return true;
|
||||
}
|
||||
|
||||
static handle cast(const WPyStruct &src, py::return_value_policy policy,
|
||||
static handle cast(const WPyStruct& src, py::return_value_policy policy,
|
||||
py::handle parent) {
|
||||
py::handle v = src.py;
|
||||
v.inc_ref();
|
||||
@@ -72,8 +72,7 @@ template <> struct type_caster<WPyStruct> {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace pybind11
|
||||
} // namespace pybind11::detail
|
||||
|
||||
//
|
||||
// Struct info class implementation
|
||||
@@ -88,7 +87,7 @@ struct WPyStructConverter {
|
||||
|
||||
virtual std::string_view GetSchema() const = 0;
|
||||
|
||||
virtual void Pack(std::span<uint8_t> data, const WPyStruct &value) const = 0;
|
||||
virtual void Pack(std::span<uint8_t> data, const WPyStruct& value) const = 0;
|
||||
|
||||
virtual WPyStruct Unpack(std::span<const uint8_t> data) const = 0;
|
||||
|
||||
@@ -96,12 +95,13 @@ struct WPyStructConverter {
|
||||
// std::span<const uint8_t> data) const = 0;
|
||||
|
||||
virtual void ForEachNested(
|
||||
const std::function<void(std::string_view, std::string_view)> &fn)
|
||||
const std::function<void(std::string_view, std::string_view)>& fn)
|
||||
const = 0;
|
||||
};
|
||||
|
||||
// static C++ converter
|
||||
template <typename T> struct WPyStructCppConverter : WPyStructConverter {
|
||||
template <typename T>
|
||||
struct WPyStructCppConverter : WPyStructConverter {
|
||||
std::string_view GetTypeName() const override {
|
||||
return wpi::util::Struct<T>::GetTypeName();
|
||||
}
|
||||
@@ -112,9 +112,9 @@ template <typename T> struct WPyStructCppConverter : WPyStructConverter {
|
||||
return wpi::util::Struct<T>::GetSchema();
|
||||
}
|
||||
|
||||
void Pack(std::span<uint8_t> data, const WPyStruct &value) const override {
|
||||
void Pack(std::span<uint8_t> data, const WPyStruct& value) const override {
|
||||
py::gil_scoped_acquire gil;
|
||||
const T &v = value.py.cast<const T &>();
|
||||
const T& v = value.py.cast<const T&>();
|
||||
wpi::util::Struct<T>::Pack(data, v);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ template <typename T> struct WPyStructCppConverter : WPyStructConverter {
|
||||
// }
|
||||
|
||||
void ForEachNested(
|
||||
const std::function<void(std::string_view, std::string_view)> &fn)
|
||||
const std::function<void(std::string_view, std::string_view)>& fn)
|
||||
const override {
|
||||
if constexpr (wpi::util::HasNestedStruct<T>) {
|
||||
wpi::util::Struct<T>::ForEachNested(fn);
|
||||
@@ -139,13 +139,13 @@ template <typename T> struct WPyStructCppConverter : WPyStructConverter {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> void SetupWPyStruct(auto pycls) {
|
||||
|
||||
auto *sptr =
|
||||
template <typename T>
|
||||
void SetupWPyStruct(auto pycls) {
|
||||
auto* sptr =
|
||||
new std::shared_ptr<WPyStructConverter>(new WPyStructCppConverter<T>());
|
||||
|
||||
py::capsule c(sptr, "WPyStruct", [](void *ptr) {
|
||||
delete (std::shared_ptr<WPyStructConverter> *)ptr;
|
||||
py::capsule c(sptr, "WPyStruct", [](void* ptr) {
|
||||
delete (std::shared_ptr<WPyStructConverter>*)ptr;
|
||||
});
|
||||
|
||||
pycls.def_property_readonly_static("WPIStruct",
|
||||
@@ -154,8 +154,7 @@ template <typename T> void SetupWPyStruct(auto pycls) {
|
||||
|
||||
// dynamic python converter
|
||||
struct WPyStructPyConverter : WPyStructConverter {
|
||||
|
||||
WPyStructPyConverter(py::object o) {
|
||||
explicit WPyStructPyConverter(py::object o) {
|
||||
m_typename = o.attr("typename").cast<std::string>();
|
||||
m_schema = o.attr("schema").cast<std::string>();
|
||||
m_size = o.attr("size").cast<size_t>();
|
||||
@@ -163,7 +162,8 @@ struct WPyStructPyConverter : WPyStructConverter {
|
||||
m_pack = py::reinterpret_borrow<py::function>(o.attr("pack"));
|
||||
m_packInto = py::reinterpret_borrow<py::function>(o.attr("packInto"));
|
||||
m_unpack = py::reinterpret_borrow<py::function>(o.attr("unpack"));
|
||||
// m_unpackInto = py::reinterpret_borrow<py::function>(o.attr("unpackInto"));
|
||||
// m_unpackInto =
|
||||
// py::reinterpret_borrow<py::function>(o.attr("unpackInto"));
|
||||
m_forEachNested =
|
||||
py::reinterpret_borrow<py::function>(o.attr("forEachNested"));
|
||||
}
|
||||
@@ -177,7 +177,7 @@ struct WPyStructPyConverter : WPyStructConverter {
|
||||
py::function m_packInto;
|
||||
py::function m_unpack;
|
||||
// py::function m_unpackInto;
|
||||
py::function m_forEachNested; // might be none
|
||||
py::function m_forEachNested; // might be none
|
||||
|
||||
std::string_view GetTypeName() const override { return m_typename; }
|
||||
|
||||
@@ -185,7 +185,7 @@ struct WPyStructPyConverter : WPyStructConverter {
|
||||
|
||||
std::string_view GetSchema() const override { return m_schema; }
|
||||
|
||||
void Pack(std::span<uint8_t> data, const WPyStruct &value) const override {
|
||||
void Pack(std::span<uint8_t> data, const WPyStruct& value) const override {
|
||||
py::gil_scoped_acquire gil;
|
||||
py::bytes result = m_pack(value.py);
|
||||
std::string_view rview = result;
|
||||
@@ -196,13 +196,13 @@ struct WPyStructPyConverter : WPyStructConverter {
|
||||
throw py::value_error(msg);
|
||||
}
|
||||
|
||||
rview.copy((char *)data.data(), rview.size());
|
||||
rview.copy(reinterpret_cast<char*>(data.data()), rview.size());
|
||||
}
|
||||
|
||||
WPyStruct Unpack(std::span<const uint8_t> data) const override {
|
||||
py::gil_scoped_acquire gil;
|
||||
auto view =
|
||||
py::memoryview::from_memory((const void *)data.data(), data.size());
|
||||
py::memoryview::from_memory((const void*)data.data(), data.size());
|
||||
return WPyStruct(m_unpack(view));
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ struct WPyStructPyConverter : WPyStructConverter {
|
||||
// }
|
||||
|
||||
void ForEachNested(
|
||||
const std::function<void(std::string_view, std::string_view)> &fn)
|
||||
const std::function<void(std::string_view, std::string_view)>& fn)
|
||||
const override {
|
||||
py::gil_scoped_acquire gil;
|
||||
if (!m_forEachNested.is_none()) {
|
||||
@@ -227,9 +227,8 @@ struct WPyStructPyConverter : WPyStructConverter {
|
||||
// passed as I... to the wpi::util::Struct methods
|
||||
struct WPyStructInfo {
|
||||
WPyStructInfo() = default;
|
||||
WPyStructInfo(const py::type &t) {
|
||||
explicit WPyStructInfo(const py::type& t) {
|
||||
if (!py::hasattr(t, "WPIStruct")) {
|
||||
|
||||
throw py::type_error(
|
||||
fmt::format("{} is not struct serializable (does not have WPIStruct)",
|
||||
pytypename(t)));
|
||||
@@ -238,9 +237,9 @@ struct WPyStructInfo {
|
||||
py::object s = t.attr("WPIStruct");
|
||||
|
||||
// C++ version
|
||||
void *c = PyCapsule_GetPointer(s.ptr(), "WPyStruct");
|
||||
void* c = PyCapsule_GetPointer(s.ptr(), "WPyStruct");
|
||||
if (c != NULL) {
|
||||
cvt = *(std::shared_ptr<WPyStructConverter> *)c;
|
||||
cvt = *(std::shared_ptr<WPyStructConverter>*)c;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -249,7 +248,7 @@ struct WPyStructInfo {
|
||||
// Python version
|
||||
try {
|
||||
cvt = std::make_shared<WPyStructPyConverter>(s);
|
||||
} catch (py::error_already_set &e) {
|
||||
} catch (py::error_already_set& e) {
|
||||
std::string msg = fmt::format(
|
||||
"{} is not struct serializable (invalid WPIStruct)", pytypename(t));
|
||||
py::raise_from(e, PyExc_TypeError, msg.c_str());
|
||||
@@ -257,10 +256,11 @@ struct WPyStructInfo {
|
||||
}
|
||||
}
|
||||
|
||||
WPyStructInfo(const WPyStruct &v) : WPyStructInfo(py::type::of(v.py)) {}
|
||||
explicit WPyStructInfo(const WPyStruct& v)
|
||||
: WPyStructInfo(py::type::of(v.py)) {}
|
||||
|
||||
const WPyStructConverter* operator->() const {
|
||||
const auto *c = cvt.get();
|
||||
const auto* c = cvt.get();
|
||||
if (c == nullptr) {
|
||||
// TODO: would be nice to have a better error here, but we don't have
|
||||
// a good way to know our current context
|
||||
@@ -269,27 +269,26 @@ struct WPyStructInfo {
|
||||
return c;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
// holds something used to do serialization
|
||||
std::shared_ptr<WPyStructConverter> cvt;
|
||||
};
|
||||
|
||||
// Leverages the converter stored in WPyStructInfo to do the actual work
|
||||
template <> struct wpi::util::Struct<WPyStruct, WPyStructInfo> {
|
||||
static std::string_view GetTypeName(const WPyStructInfo &info) {
|
||||
template <>
|
||||
struct wpi::util::Struct<WPyStruct, WPyStructInfo> {
|
||||
static std::string_view GetTypeName(const WPyStructInfo& info) {
|
||||
return info->GetTypeName();
|
||||
}
|
||||
|
||||
static size_t GetSize(const WPyStructInfo &info) {
|
||||
return info->GetSize();
|
||||
}
|
||||
static size_t GetSize(const WPyStructInfo& info) { return info->GetSize(); }
|
||||
|
||||
static std::string_view GetSchema(const WPyStructInfo &info) {
|
||||
static std::string_view GetSchema(const WPyStructInfo& info) {
|
||||
return info->GetSchema();
|
||||
}
|
||||
|
||||
static WPyStruct Unpack(std::span<const uint8_t> data,
|
||||
const WPyStructInfo &info) {
|
||||
const WPyStructInfo& info) {
|
||||
return info->Unpack(data);
|
||||
}
|
||||
|
||||
@@ -298,14 +297,14 @@ template <> struct wpi::util::Struct<WPyStruct, WPyStructInfo> {
|
||||
// info->UnpackInto(v, data);
|
||||
// }
|
||||
|
||||
static void Pack(std::span<uint8_t> data, const WPyStruct &value,
|
||||
const WPyStructInfo &info) {
|
||||
static void Pack(std::span<uint8_t> data, const WPyStruct& value,
|
||||
const WPyStructInfo& info) {
|
||||
info->Pack(data, value);
|
||||
}
|
||||
|
||||
static void
|
||||
ForEachNested(std::invocable<std::string_view, std::string_view> auto fn,
|
||||
const WPyStructInfo &info) {
|
||||
static void ForEachNested(
|
||||
std::invocable<std::string_view, std::string_view> auto fn,
|
||||
const WPyStructInfo& info) {
|
||||
info->ForEachNested(fn);
|
||||
}
|
||||
};
|
||||
@@ -314,4 +313,5 @@ static_assert(wpi::util::StructSerializable<WPyStruct, WPyStructInfo>);
|
||||
static_assert(wpi::util::HasNestedStruct<WPyStruct, WPyStructInfo>);
|
||||
|
||||
// This breaks on readonly structs, so we disable for now
|
||||
// static_assert(wpi::util::MutableStructSerializable<WPyStruct, WPyStructInfo>);
|
||||
// static_assert(wpi::util::MutableStructSerializable<WPyStruct,
|
||||
// WPyStructInfo>);
|
||||
|
||||
@@ -1,51 +1,53 @@
|
||||
|
||||
#include "wpystruct_fns.h"
|
||||
|
||||
#include "wpystruct.h"
|
||||
|
||||
void forEachNested(
|
||||
const py::type &t,
|
||||
const std::function<void(std::string_view, std::string_view)> &fn) {
|
||||
const py::type& t,
|
||||
const std::function<void(std::string_view, std::string_view)>& fn) {
|
||||
WPyStructInfo info(t);
|
||||
wpi::util::ForEachStructSchema<WPyStruct, WPyStructInfo>(fn, info);
|
||||
}
|
||||
|
||||
py::str getTypeName(const py::type &t) {
|
||||
py::str getTypeName(const py::type& t) {
|
||||
WPyStructInfo info(t);
|
||||
return wpi::util::GetStructTypeName<WPyStruct, WPyStructInfo>(info);
|
||||
}
|
||||
|
||||
py::str getSchema(const py::type &t) {
|
||||
py::str getSchema(const py::type& t) {
|
||||
WPyStructInfo info(t);
|
||||
return wpi::util::GetStructSchema<WPyStruct, WPyStructInfo>(info);
|
||||
}
|
||||
|
||||
size_t getSize(const py::type &t) {
|
||||
size_t getSize(const py::type& t) {
|
||||
WPyStructInfo info(t);
|
||||
return wpi::util::GetStructSize<WPyStruct>(info);
|
||||
}
|
||||
|
||||
py::bytes pack(const WPyStruct &v) {
|
||||
py::bytes pack(const WPyStruct& v) {
|
||||
WPyStructInfo info(v);
|
||||
|
||||
auto sz = wpi::util::GetStructSize<WPyStruct>(info);
|
||||
PyObject *b = PyBytes_FromStringAndSize(NULL, sz);
|
||||
PyObject* b = PyBytes_FromStringAndSize(NULL, sz);
|
||||
if (b == NULL) {
|
||||
throw py::error_already_set();
|
||||
}
|
||||
|
||||
char *pybuf;
|
||||
char* pybuf;
|
||||
py::ssize_t pysz;
|
||||
if (PyBytes_AsStringAndSize(b, &pybuf, &pysz) != 0) {
|
||||
Py_DECREF(b);
|
||||
throw py::error_already_set();
|
||||
}
|
||||
|
||||
auto s = std::span((uint8_t *)pybuf, pysz);
|
||||
auto s = std::span(reinterpret_cast<uint8_t*>(pybuf), pysz);
|
||||
wpi::util::PackStruct(s, v, info);
|
||||
|
||||
return py::reinterpret_steal<py::bytes>(b);
|
||||
}
|
||||
|
||||
py::bytes packArray(const py::sequence &seq) {
|
||||
py::bytes packArray(const py::sequence& seq) {
|
||||
auto len = seq.size();
|
||||
if (len == 0) {
|
||||
return {};
|
||||
@@ -53,14 +55,14 @@ py::bytes packArray(const py::sequence &seq) {
|
||||
|
||||
WPyStructInfo info(py::type::of(seq[0]));
|
||||
auto sz = wpi::util::GetStructSize<WPyStruct>(info);
|
||||
auto total = sz*len;
|
||||
auto total = sz * len;
|
||||
|
||||
PyObject *b = PyBytes_FromStringAndSize(NULL, total);
|
||||
PyObject* b = PyBytes_FromStringAndSize(NULL, total);
|
||||
if (b == NULL) {
|
||||
throw py::error_already_set();
|
||||
}
|
||||
|
||||
char *pybuf;
|
||||
char* pybuf;
|
||||
py::ssize_t pysz;
|
||||
if (PyBytes_AsStringAndSize(b, &pybuf, &pysz) != 0) {
|
||||
Py_DECREF(b);
|
||||
@@ -69,9 +71,9 @@ py::bytes packArray(const py::sequence &seq) {
|
||||
|
||||
auto bytes_obj = py::reinterpret_steal<py::bytes>(b);
|
||||
|
||||
for (const auto &v: seq) {
|
||||
for (const auto& v : seq) {
|
||||
WPyStruct wv(v);
|
||||
auto s = std::span((uint8_t *)pybuf, sz);
|
||||
auto s = std::span(reinterpret_cast<uint8_t*>(pybuf), sz);
|
||||
wpi::util::PackStruct(s, wv, info);
|
||||
pybuf += sz;
|
||||
}
|
||||
@@ -79,7 +81,7 @@ py::bytes packArray(const py::sequence &seq) {
|
||||
return bytes_obj;
|
||||
}
|
||||
|
||||
void packInto(const WPyStruct &v, py::buffer &b) {
|
||||
void packInto(const WPyStruct& v, py::buffer& b) {
|
||||
WPyStructInfo info(v);
|
||||
py::ssize_t sz = wpi::util::GetStructSize<WPyStruct>(info);
|
||||
|
||||
@@ -94,11 +96,11 @@ void packInto(const WPyStruct &v, py::buffer &b) {
|
||||
throw py::value_error("buffer must be " + std::to_string(sz) + " bytes");
|
||||
}
|
||||
|
||||
auto s = std::span((uint8_t *)req.ptr, req.size);
|
||||
auto s = std::span(reinterpret_cast<uint8_t*>(req.ptr), req.size);
|
||||
wpi::util::PackStruct(s, v, info);
|
||||
}
|
||||
|
||||
WPyStruct unpack(const py::type &t, const py::buffer &b) {
|
||||
WPyStruct unpack(const py::type& t, const py::buffer& b) {
|
||||
WPyStructInfo info(t);
|
||||
py::ssize_t sz = wpi::util::GetStructSize<WPyStruct>(info);
|
||||
|
||||
@@ -113,11 +115,12 @@ WPyStruct unpack(const py::type &t, const py::buffer &b) {
|
||||
throw py::value_error("buffer must be " + std::to_string(sz) + " bytes");
|
||||
}
|
||||
|
||||
auto s = std::span((const uint8_t *)req.ptr, req.size);
|
||||
auto s = std::span(reinterpret_cast<const uint8_t*>(req.ptr), req.size);
|
||||
return wpi::util::UnpackStruct<WPyStruct, WPyStructInfo>(s, info);
|
||||
}
|
||||
|
||||
py::typing::List<WPyStruct> unpackArray(const py::type &t, const py::buffer &b) {
|
||||
py::typing::List<WPyStruct> unpackArray(const py::type& t,
|
||||
const py::buffer& b) {
|
||||
WPyStructInfo info(t);
|
||||
py::ssize_t sz = wpi::util::GetStructSize<WPyStruct>(info);
|
||||
|
||||
@@ -129,12 +132,13 @@ py::typing::List<WPyStruct> unpackArray(const py::type &t, const py::buffer &b)
|
||||
}
|
||||
|
||||
if (req.size % sz != 0) {
|
||||
throw py::value_error("buffer must be multiple of " + std::to_string(sz) + " bytes");
|
||||
throw py::value_error("buffer must be multiple of " + std::to_string(sz) +
|
||||
" bytes");
|
||||
}
|
||||
|
||||
auto items = req.size / sz;
|
||||
py::list a(items);
|
||||
const uint8_t *ptr = (const uint8_t *)req.ptr;
|
||||
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(req.ptr);
|
||||
for (py::ssize_t i = 0; i < items; i++) {
|
||||
auto s = std::span(ptr, sz);
|
||||
auto v = wpi::util::UnpackStruct<WPyStruct, WPyStructInfo>(s, info);
|
||||
|
||||
@@ -7,50 +7,50 @@
|
||||
Call a function to retrieve the (type string, schema) for each nested struct
|
||||
*/
|
||||
void forEachNested(
|
||||
const py::type &t,
|
||||
const std::function<void(std::string_view, std::string_view)> &fn);
|
||||
const py::type& t,
|
||||
const std::function<void(std::string_view, std::string_view)>& fn);
|
||||
|
||||
/**
|
||||
Retrieve the type name for the specified type
|
||||
*/
|
||||
py::str getTypeName(const py::type &t);
|
||||
py::str getTypeName(const py::type& t);
|
||||
|
||||
/**
|
||||
Retrieve schema for the specified type
|
||||
*/
|
||||
py::str getSchema(const py::type &t);
|
||||
py::str getSchema(const py::type& t);
|
||||
|
||||
/**
|
||||
Returns the serialized size in bytes
|
||||
*/
|
||||
size_t getSize(const py::type &t);
|
||||
size_t getSize(const py::type& t);
|
||||
|
||||
/**
|
||||
Serialize object into byte buffer
|
||||
*/
|
||||
py::bytes pack(const WPyStruct &v);
|
||||
py::bytes pack(const WPyStruct& v);
|
||||
|
||||
/**
|
||||
Serialize objects into byte buffer
|
||||
*/
|
||||
py::bytes packArray(const py::sequence &seq);
|
||||
py::bytes packArray(const py::sequence& seq);
|
||||
|
||||
/**
|
||||
Serialize object into byte buffer. Buffer must be exact size.
|
||||
*/
|
||||
void packInto(const WPyStruct &v, py::buffer &b);
|
||||
void packInto(const WPyStruct& v, py::buffer& b);
|
||||
|
||||
/**
|
||||
Convert byte buffer into object of specified type. Buffer must be exact
|
||||
size.
|
||||
*/
|
||||
WPyStruct unpack(const py::type &t, const py::buffer &b);
|
||||
WPyStruct unpack(const py::type& t, const py::buffer& b);
|
||||
|
||||
/**
|
||||
Convert byte buffer into list of objects of specified type. Buffer must be
|
||||
exact size.
|
||||
*/
|
||||
py::typing::List<WPyStruct> unpackArray(const py::type &t, const py::buffer &b);
|
||||
py::typing::List<WPyStruct> unpackArray(const py::type& t, const py::buffer& b);
|
||||
|
||||
// /**
|
||||
// Convert byte buffer into passed in object. Buffer must be exact
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
@@ -178,7 +180,6 @@ StructWithWPI_String cast_struct_with_wpi_string() {
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(module, m) {
|
||||
|
||||
sendable_test(m);
|
||||
struct_test(m);
|
||||
|
||||
@@ -209,7 +210,7 @@ PYBIND11_MODULE(module, m) {
|
||||
m.def("load_stringmap_int", &load_stringmap_int);
|
||||
m.def("cast_stringmap", &cast_stringmap);
|
||||
// JSON
|
||||
m.def("cast_json_arg", &cast_json_arg);
|
||||
m.def("cast_json_arg", &cast_json_arg);
|
||||
m.def("cast_json_val", &cast_json_val);
|
||||
m.attr("max_uint64") = std::numeric_limits<uint64_t>::max();
|
||||
m.attr("max_int64") = std::numeric_limits<int64_t>::max();
|
||||
@@ -220,7 +221,7 @@ PYBIND11_MODULE(module, m) {
|
||||
// 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);
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <semiwrap.h>
|
||||
|
||||
#include "wpi/util/sendable/SendableBuilder.hpp"
|
||||
#include "wpi/util/sendable/SendableRegistry.hpp"
|
||||
|
||||
class MySendableBuilder : public wpi::util::SendableBuilder {
|
||||
public:
|
||||
MySendableBuilder(py::dict keys) : keys(keys) {}
|
||||
public:
|
||||
explicit MySendableBuilder(py::dict keys) : keys(keys) {}
|
||||
|
||||
~MySendableBuilder() {
|
||||
~MySendableBuilder() override {
|
||||
// leak this so the python interpreter doesn't crash on shutdown
|
||||
keys.release();
|
||||
}
|
||||
@@ -42,9 +47,9 @@ public:
|
||||
|
||||
void PublishConstDouble(std::string_view key, double value) override {}
|
||||
|
||||
void
|
||||
AddStringProperty(std::string_view key, std::function<std::string()> getter,
|
||||
std::function<void(std::string_view)> setter) override {}
|
||||
void AddStringProperty(
|
||||
std::string_view key, std::function<std::string()> getter,
|
||||
std::function<void(std::string_view)> setter) override {}
|
||||
|
||||
void PublishConstString(std::string_view key,
|
||||
std::string_view value) override {}
|
||||
@@ -94,44 +99,48 @@ public:
|
||||
|
||||
void AddSmallStringProperty(
|
||||
std::string_view key,
|
||||
std::function<std::string_view(wpi::util::SmallVectorImpl<char> &buf)> getter,
|
||||
std::function<std::string_view(wpi::util::SmallVectorImpl<char>& buf)>
|
||||
getter,
|
||||
std::function<void(std::string_view)> setter) override {}
|
||||
|
||||
void AddSmallBooleanArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<std::span<const int>(wpi::util::SmallVectorImpl<int> &buf)>
|
||||
std::function<std::span<const int>(wpi::util::SmallVectorImpl<int>& buf)>
|
||||
getter,
|
||||
std::function<void(std::span<const int>)> setter) override {}
|
||||
|
||||
void AddSmallIntegerArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<
|
||||
std::span<const int64_t>(wpi::util::SmallVectorImpl<int64_t> &buf)>
|
||||
std::span<const int64_t>(wpi::util::SmallVectorImpl<int64_t>& buf)>
|
||||
getter,
|
||||
std::function<void(std::span<const int64_t>)> setter) override {}
|
||||
|
||||
void AddSmallFloatArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<std::span<const float>(wpi::util::SmallVectorImpl<float> &buf)>
|
||||
std::function<
|
||||
std::span<const float>(wpi::util::SmallVectorImpl<float>& buf)>
|
||||
getter,
|
||||
std::function<void(std::span<const float>)> setter) override {}
|
||||
|
||||
void AddSmallDoubleArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<std::span<const double>(wpi::util::SmallVectorImpl<double> &buf)>
|
||||
std::function<
|
||||
std::span<const double>(wpi::util::SmallVectorImpl<double>& buf)>
|
||||
getter,
|
||||
std::function<void(std::span<const double>)> setter) override {}
|
||||
|
||||
void AddSmallStringArrayProperty(
|
||||
std::string_view key,
|
||||
std::function<
|
||||
std::span<const std::string>(wpi::util::SmallVectorImpl<std::string> &buf)>
|
||||
std::function<std::span<const std::string>(
|
||||
wpi::util::SmallVectorImpl<std::string>& buf)>
|
||||
getter,
|
||||
std::function<void(std::span<const std::string>)> setter) override {}
|
||||
|
||||
void AddSmallRawProperty(
|
||||
std::string_view key, std::string_view typeString,
|
||||
std::function<std::span<uint8_t>(wpi::util::SmallVectorImpl<uint8_t> &buf)>
|
||||
std::function<
|
||||
std::span<uint8_t>(wpi::util::SmallVectorImpl<uint8_t>& buf)>
|
||||
getter,
|
||||
std::function<void(std::span<const uint8_t>)> setter) override {}
|
||||
|
||||
@@ -151,4 +160,6 @@ void Publish(wpi::util::SendableRegistry::UID sendableUid, py::dict keys) {
|
||||
wpi::util::SendableRegistry::Publish(sendableUid, std::move(builder));
|
||||
}
|
||||
|
||||
void sendable_test(py::module &m) { m.def("publish", Publish); }
|
||||
void sendable_test(py::module& m) {
|
||||
m.def("publish", Publish);
|
||||
}
|
||||
|
||||
@@ -8,33 +8,34 @@
|
||||
|
||||
struct ThingA {
|
||||
ThingA() = default;
|
||||
ThingA(int x) : x(x) {}
|
||||
explicit ThingA(int x) : x(x) {}
|
||||
|
||||
const int x = 0;
|
||||
|
||||
bool operator==(const ThingA &other) const { return x == other.x; }
|
||||
bool operator==(const ThingA& other) const { return x == other.x; }
|
||||
};
|
||||
|
||||
template <> struct wpi::util::Struct<ThingA> {
|
||||
template <>
|
||||
struct wpi::util::Struct<ThingA> {
|
||||
static constexpr std::string_view GetTypeName() { return "ThingA"; }
|
||||
static constexpr size_t GetSize() { return 1; }
|
||||
static constexpr std::string_view GetSchema() { return "uint8 value"; }
|
||||
static ThingA Unpack(std::span<const uint8_t> data) {
|
||||
return ThingA{data[0]};
|
||||
}
|
||||
static void Pack(std::span<uint8_t> data, const ThingA &value) {
|
||||
static void Pack(std::span<uint8_t> data, const ThingA& value) {
|
||||
data[0] = value.x;
|
||||
}
|
||||
};
|
||||
|
||||
struct Outer {
|
||||
Outer() = default;
|
||||
Outer(const ThingA &t, int c) : inner(t), c(c) {}
|
||||
Outer(const ThingA& t, int c) : inner(t), c(c) {}
|
||||
|
||||
ThingA inner;
|
||||
int c = 0;
|
||||
|
||||
bool operator==(const Outer &other) const {
|
||||
bool operator==(const Outer& other) const {
|
||||
return inner == other.inner && c == other.c;
|
||||
}
|
||||
};
|
||||
@@ -42,7 +43,9 @@ struct Outer {
|
||||
template <>
|
||||
struct wpi::util::Struct<Outer> {
|
||||
static constexpr std::string_view GetTypeName() { return "Outer"; }
|
||||
static constexpr size_t GetSize() { return wpi::util::GetStructSize<ThingA>() + 4; }
|
||||
static constexpr size_t GetSize() {
|
||||
return wpi::util::GetStructSize<ThingA>() + 4;
|
||||
}
|
||||
static constexpr std::string_view GetSchema() {
|
||||
return "ThingA inner; int32 c";
|
||||
}
|
||||
@@ -63,8 +66,7 @@ struct wpi::util::Struct<Outer> {
|
||||
}
|
||||
};
|
||||
|
||||
void struct_test(py::module &m) {
|
||||
|
||||
void struct_test(py::module& m) {
|
||||
py::class_<ThingA> thingCls(m, "ThingA");
|
||||
thingCls.def(py::init<>());
|
||||
thingCls.def(py::init<int>());
|
||||
@@ -81,4 +83,4 @@ void struct_test(py::module &m) {
|
||||
outerCls.def(py::self == py::self);
|
||||
|
||||
SetupWPyStruct<Outer>(outerCls);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#include <semiwrap_init.xrp._xrp.hpp>
|
||||
#include "semiwrap_init.xrp._xrp.hpp"
|
||||
|
||||
SEMIWRAP_PYBIND11_MODULE(m) {
|
||||
initWrapper(m);
|
||||
}
|
||||
initWrapper(m);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ pkgconf_pypi_initpy=xrp._init__xrp
|
||||
|
||||
Name: xrp
|
||||
Description: semiwrap pybind11 module
|
||||
Version:
|
||||
Version:
|
||||
Cflags: -I${prefix}
|
||||
Requires: robotpy-native-xrp wpilib wpimath
|
||||
|
||||
Reference in New Issue
Block a user