diff --git a/src/xrt/auxiliary/util/CMakeLists.txt b/src/xrt/auxiliary/util/CMakeLists.txt index c185d226d..1c2ed3670 100644 --- a/src/xrt/auxiliary/util/CMakeLists.txt +++ b/src/xrt/auxiliary/util/CMakeLists.txt @@ -80,6 +80,8 @@ add_library( u_trace_marker.h u_var.cpp u_var.h + u_vector.cpp + u_vector.h u_config_json.c u_config_json.h u_verify.h diff --git a/src/xrt/auxiliary/util/u_vector.cpp b/src/xrt/auxiliary/util/u_vector.cpp new file mode 100644 index 000000000..3a9624f4f --- /dev/null +++ b/src/xrt/auxiliary/util/u_vector.cpp @@ -0,0 +1,44 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Expose std::vector to C + * @author Mateo de Mayo + * @ingroup aux_util + */ + +#include "u_vector.h" +#include + +using std::vector; + +#define U_VECTOR_IMPLEMENTATION(TYPE) \ + u_vector_##TYPE u_vector_##TYPE##_create() \ + { \ + u_vector_##TYPE uv{new vector}; \ + return uv; \ + } \ + \ + void u_vector_##TYPE##_push_back(u_vector_##TYPE uv, TYPE e) \ + { \ + vector *v = static_cast *>(uv.ptr); \ + v->push_back(e); \ + } \ + \ + TYPE u_vector_##TYPE##_at(u_vector_##TYPE uv, size_t i) \ + { \ + vector *v = static_cast *>(uv.ptr); \ + return v->at(i); \ + } \ + \ + void u_vector_##TYPE##_destroy(u_vector_##TYPE *uv) \ + { \ + vector *v = static_cast *>(uv->ptr); \ + delete v; \ + uv->ptr = nullptr; \ + } + +extern "C" { +U_VECTOR_IMPLEMENTATION(int) +U_VECTOR_IMPLEMENTATION(float) +} diff --git a/src/xrt/auxiliary/util/u_vector.h b/src/xrt/auxiliary/util/u_vector.h new file mode 100644 index 000000000..761665b9e --- /dev/null +++ b/src/xrt/auxiliary/util/u_vector.h @@ -0,0 +1,33 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Expose std::vector to C + * @author Mateo de Mayo + * @ingroup aux_util + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define U_VECTOR_DECLARATION(TYPE) \ + struct u_vector_##TYPE \ + { \ + void *ptr; \ + }; \ + struct u_vector_##TYPE u_vector_##TYPE##_create(); \ + void u_vector_##TYPE##_push_back(struct u_vector_##TYPE uv, TYPE e); \ + TYPE u_vector_##TYPE##_at(struct u_vector_##TYPE uv, size_t i); \ + void u_vector_##TYPE##_destroy(struct u_vector_##TYPE *uv); + +U_VECTOR_DECLARATION(int) +U_VECTOR_DECLARATION(float) + +#ifdef __cplusplus +} +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8bb004adf..7607270c4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ set(tests tests_pacing tests_quatexpmap tests_rational + tests_vector tests_worker tests_pose ) diff --git a/tests/tests_vector.cpp b/tests/tests_vector.cpp new file mode 100644 index 000000000..dc272d146 --- /dev/null +++ b/tests/tests_vector.cpp @@ -0,0 +1,38 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Test u_vector C interface. + * @author Mateo de Mayo + */ + +#include "catch/catch.hpp" +#include "util/u_vector.h" + +TEST_CASE("u_vector") +{ + SECTION("Test interface generated from macros") + { + struct u_vector_float vf = u_vector_float_create(); + CHECK(vf.ptr != NULL); + + constexpr float A = 2.71f; + constexpr float B = 1.61f; + constexpr float C = 3.14f; + + u_vector_float_push_back(vf, A); + u_vector_float_push_back(vf, B); + u_vector_float_push_back(vf, C); + + float a = u_vector_float_at(vf, 0); + float b = u_vector_float_at(vf, 1); + float c = u_vector_float_at(vf, 2); + + CHECK(a == A); + CHECK(b == B); + CHECK(c == C); + + u_vector_float_destroy(&vf); + CHECK(vf.ptr == NULL); + } +}