From 4049bc357b9066559acbd52f480110861b074e08 Mon Sep 17 00:00:00 2001 From: Joseph Angelo Date: Mon, 14 Oct 2019 13:19:42 -0700 Subject: [PATCH 1/2] Added C++ header files that define a couple of wrapper types Added steps to autogenerate SBP message traits for the C++ headers Regenerated the C files --- c/include/libsbp/cpp/message_handler.h | 174 +++ c/include/libsbp/cpp/message_traits.h | 1026 +++++++++++++++++ c/include/libsbp/cpp/state.h | 82 ++ generator/sbpg/generator.py | 2 + generator/sbpg/targets/c.py | 21 + .../resources/sbp_message_traits_template.h | 43 + 6 files changed, 1348 insertions(+) create mode 100644 c/include/libsbp/cpp/message_handler.h create mode 100644 c/include/libsbp/cpp/message_traits.h create mode 100644 c/include/libsbp/cpp/state.h create mode 100644 generator/sbpg/targets/resources/sbp_message_traits_template.h diff --git a/c/include/libsbp/cpp/message_handler.h b/c/include/libsbp/cpp/message_handler.h new file mode 100644 index 0000000000..734f388343 --- /dev/null +++ b/c/include/libsbp/cpp/message_handler.h @@ -0,0 +1,174 @@ +/** + * Copyright (C) 2019 Swift Navigation Inc. + * Contact: Swift Navigation + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef SBP_CPP_MESSAGE_HANDLER_H_ +#define SBP_CPP_MESSAGE_HANDLER_H_ + +#include +#include + +#include +#include + +namespace sbp { + +/** + * A convenience type alias for class member functions that accept SBP message callbacks + */ +template +using CallbackMemFn = void (ClassT::*)(uint16_t, uint8_t, const ArgT &); + +/** + * A helper function for calling a C++ object member function from a libsbp callback. + * + * This function is registered with libsbp as a callback and calls a specific member function + * of an object from that callback with the SBP message decoded. The member function pointer + * is encoded into the template parameter, and the instance of the object is passed in via + * the `context` parameter. + * + * @tparam MsgT The message type to decode the payload as + * @tparam ClassT The class type to call the function on + * @tparam func Pointer to the member function to call + * + * @param sender_id The decoded sender ID, is forwarded on to `func` + * @param len The length of the message, is forwarded on to `func` + * @param msg The raw message payload + * @param context Pointer to an instance of `ClassT` to call `func` on + */ +template func> +inline void sbp_cb_passthrough(uint16_t sender_id, uint8_t len, uint8_t msg[], void *context) { + assert(nullptr != context); + + auto instance = static_cast(context); + auto val = reinterpret_cast(msg); + ((*instance).*(func))(sender_id, len, *val); +} + +namespace details { + +/** + * Recursive interface type for defining the interface functions for `MessageHandler`. + * + * These types define a virtual `operator()` for handling a specific SBP message type, + * as well as a function for registering it as a SBP callback. + * + * @note These types aren't meant to be used directly by application code. + * + * @tparam MsgType The type of SBP message to define an interface for + * @tparam OtherTypes Other types to recursively define interfaces for + */ +template +class CallbackInterface : CallbackInterface { + public: + CallbackInterface() = default; + virtual ~CallbackInterface() = default; + + using CallbackInterface::handle_sbp_msg; + virtual void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const MsgType& msg) = 0; + + protected: + void register_callback(sbp_state_t *state, sbp_msg_callbacks_node_t nodes[]) { + sbp_register_callback(state, + sbp::MessageTraits::id, + &sbp_cb_passthrough, + this, + &nodes[0]); + CallbackInterface::register_callback(state, &nodes[1]); + } +}; + +template +class CallbackInterface { + public: + CallbackInterface() = default; + virtual ~CallbackInterface() = default; + + virtual void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const MsgType& msg) = 0; + protected: + void register_callback(sbp_state_t *state, sbp_msg_callbacks_node_t nodes[]) { + sbp_register_callback(state, + sbp::MessageTraits::id, + &sbp_cb_passthrough, + this, + &nodes[0]); + } +}; + +} // namespace details + +/** + * Base type for defining classes that handle SBP messages + * + * Application classes should derive from this class if they wish to handle + * SBP messages with a member function. `MessageHandler` instantiates all of + * the callback nodes, and registers the member functions with the given + * `sbp_state_t`. + * + * Classes that derive from `MessageHandler` need to implement + * void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const MsgType& msg) const; + * for each `MsgType` in the list of message types given as template parameters. + * + * Due to the nature of the callback registration in libsbp we dissallow copying or + * moving of `MessageHandler`. + * + * @note It should not matter if the class derives publicly or privately from `MessageHandler` + * or if the `handle_sbp_msg` functions are public or private. + * + * @example + * class ECEFHandler : private sbp::MessageHandler { + * public: + * ECEFHandler(sbp::State *state) : sbp::MessageHandler(state) { + * // The callbacks have already been registered + * // Perform other initialization tasks + * } + * + * void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const msg_gps_time_t& msg) { + * // handle GPS time message + * } + * + * void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const msg_pos_ecef_t& msg) { + * // handle pos ECEF message + * } + * }; + * + * @tparam MsgTypes List of SBP message types to register callbacks for + */ +template + class MessageHandler : public details::CallbackInterface { + static constexpr size_t kMsgCount = sizeof...(MsgTypes); + + State &state_; + std::array callback_nodes_; + + public: + + explicit MessageHandler(State *state) : details::CallbackInterface(), state_(*state), callback_nodes_() { + details::CallbackInterface::register_callback(state_.get_state(), callback_nodes_.data()); + } + + virtual ~MessageHandler() { + for (auto& node : callback_nodes_) { + sbp_remove_callback(state_.get_state(), &node); + } + } + + MessageHandler(const MessageHandler&) = delete; + MessageHandler(MessageHandler&& other) = delete; + MessageHandler& operator=(const MessageHandler&) = delete; + MessageHandler& operator=(MessageHandler&&) = delete; + + using details::CallbackInterface::handle_sbp_msg; +}; + +} /* namespace sbp */ + +#endif /* SBP_CPP_MESSAGE_HANDLER_H_ */ diff --git a/c/include/libsbp/cpp/message_traits.h b/c/include/libsbp/cpp/message_traits.h new file mode 100644 index 0000000000..96e2c9cdfc --- /dev/null +++ b/c/include/libsbp/cpp/message_traits.h @@ -0,0 +1,1026 @@ +/** + * Copyright (C) 2019 Swift Navigation Inc. + * Contact: Swift Navigation + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef SBP_CPP_MESSAGE_TRAITS_H +#define SBP_CPP_MESSAGE_TRAITS_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sbp { + +template +struct MessageTraits { }; + + +template<> +struct MessageTraits { + static constexpr u16 id = 16; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 17; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 19; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 20; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 21; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 22; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 23; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 24; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 25; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 26; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 27; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 28; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 29; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 30; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 31; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 33; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 34; +}; + + + +template<> +struct MessageTraits { + static constexpr u16 id = 43; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 44; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 45; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 46; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 47; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 67; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 68; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 69; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 70; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 71; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 72; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 73; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 74; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 80; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 81; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 97; +}; + + + + +template<> +struct MessageTraits { + static constexpr u16 id = 112; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 113; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 114; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 115; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 117; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 128; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 129; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 130; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 131; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 132; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 133; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 134; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 135; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 136; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 137; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 138; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 139; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 140; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 141; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 142; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 144; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 145; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 146; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 147; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 148; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 149; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 150; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 151; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 160; +}; + + + +template<> +struct MessageTraits { + static constexpr u16 id = 162; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 163; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 164; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 165; +}; + + + +template<> +struct MessageTraits { + static constexpr u16 id = 167; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 168; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 169; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 170; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 171; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 172; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 173; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 174; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 175; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 176; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 177; +}; + + + + +template<> +struct MessageTraits { + static constexpr u16 id = 180; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 181; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 182; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 184; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 185; +}; + + + +template<> +struct MessageTraits { + static constexpr u16 id = 187; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 188; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 189; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 190; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 191; +}; + + + + +template<> +struct MessageTraits { + static constexpr u16 id = 221; +}; + + + +template<> +struct MessageTraits { + static constexpr u16 id = 224; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 225; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 226; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 227; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 228; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 229; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 230; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 231; +}; + + + +template<> +struct MessageTraits { + static constexpr u16 id = 243; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 256; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 257; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 258; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 259; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 431; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 512; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 513; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 514; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 515; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 516; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 517; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 518; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 519; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 520; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 521; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 522; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 523; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 524; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 525; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 526; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 527; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 528; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 529; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 530; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 531; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 532; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 533; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 544; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 545; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 546; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1024; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1025; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1026; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1500; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1501; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1505; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1510; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1515; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1520; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1525; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 1600; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 2048; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 2304; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 2305; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 2306; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 2307; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 4097; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 4098; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 30583; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32512; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32513; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32514; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32515; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32516; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32517; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32518; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 32519; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65280; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65282; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65283; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65284; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65285; +}; + + +template<> +struct MessageTraits { + static constexpr u16 id = 65535; +}; + + + + +} // namespace sbp + +#endif //SBP_CPP_MESSAGE_TRAITS_H \ No newline at end of file diff --git a/c/include/libsbp/cpp/state.h b/c/include/libsbp/cpp/state.h new file mode 100644 index 0000000000..71f75bf8dd --- /dev/null +++ b/c/include/libsbp/cpp/state.h @@ -0,0 +1,82 @@ +/** + * Copyright (C) 2019 Swift Navigation Inc. + * Contact: Swift Navigation + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef SBP_CPP_STATE_H +#define SBP_CPP_STATE_H + +#include + +namespace sbp { + +class IReader { + public: + virtual ~IReader() = default; + + virtual s32 read(u8 *buffer, u32 buffer_length) = 0; +}; + +class IWriter { + public: + virtual ~IWriter() = default; + + virtual s32 write(const u8 *buffer, u32 buffer_length) = 0; +}; + +class State { + private: + sbp_state_t state_; + IReader *reader_; + IWriter *writer_; + + static s32 read_func(u8 *buff, u32 n, void *ctx) { + State *instance = static_cast(ctx); + return instance->reader_->read(buff, n); + } + + static s32 write_func(u8 *buff, u32 n, void *ctx) { + State *instance = static_cast(ctx); + return instance->writer_->write(buff, n); + } + + public: + State() : state_(), reader_(nullptr), writer_(nullptr) { + sbp_state_init(&state_); + sbp_state_set_io_context(&state_, this); + } + + explicit State(IReader *reader, IWriter *writer) : State() { + reader_ = reader; + writer_ = writer; + } + + sbp_state_t *get_state() { return &state_; } + + void set_reader(IReader *reader) { reader_ = reader; } + + void set_writer(IWriter *writer) { writer_ = writer; } + + s8 process() { + return sbp_process(&state_, &read_func); + } + + s8 send_message(u16 msg_type, u16 sender_id, u8 length, u8 payload[]) { + return sbp_send_message(&state_, msg_type, sender_id, length, payload, &write_func); + } + + s8 process_payload(u16 sender_id, u16 msg_type, u8 msg_length, u8 payload[]) { + return sbp_process_payload(&state_, sender_id, msg_type, msg_length, payload); + } +}; + +} + +#endif //SBP_CPP_STATE_H diff --git a/generator/sbpg/generator.py b/generator/sbpg/generator.py index 6f86715a5e..e6cd1e2844 100755 --- a/generator/sbpg/generator.py +++ b/generator/sbpg/generator.py @@ -148,6 +148,8 @@ def main(): pb.render_source(output_dir, parsed) if args.c: c.render_version(output_dir, args.release[0]) + parsed = [yaml.parse_spec(spec) for spec in file_index.values()] + c.render_traits(output_dir, parsed) elif args.python: py.render_version(output_dir, args.release[0]) elif args.haskell: diff --git a/generator/sbpg/targets/c.py b/generator/sbpg/targets/c.py index 3f5d0fa2ce..adebfb5d6e 100755 --- a/generator/sbpg/targets/c.py +++ b/generator/sbpg/targets/c.py @@ -18,6 +18,7 @@ MESSAGES_TEMPLATE_NAME = "sbp_messages_template.h" VERSION_TEMPLATE_NAME = "sbp_version_template.h" +MESSAGE_TRAITS_TEMPLATE_NAME = "sbp_message_traits_template.h" def commentify(value): """ @@ -85,6 +86,7 @@ def mk_size(field): else: return '%s;' % field.identifier + JENV.filters['commentify'] = commentify JENV.filters['mk_id'] = mk_id JENV.filters['mk_size'] = mk_size @@ -112,3 +114,22 @@ def render_version(output_dir, release): py_template = JENV.get_template(VERSION_TEMPLATE_NAME) with open(destination_filename, 'w') as f: f.write(py_template.render(major=major, minor=minor, patch=patch)) + +def render_traits(output_dir, package_specs): + msgs = [] + includes = [] + for package_spec in package_specs: + if not package_spec.render_source: + continue + name = package_spec.identifier.split('.', 2)[2] + if name != 'types' and name != 'base': + includes.append(name) + for m in package_spec.definitions: + if m.static and m.sbp_id: + msgs.append(m) + destination_filename = "%s/cpp/message_traits.h" % output_dir + py_template = JENV.get_template(MESSAGE_TRAITS_TEMPLATE_NAME) + with open(destination_filename, 'w') as f: + f.write(py_template.render(packages=package_specs, + msgs=sorted(msgs, key=lambda msg: msg.sbp_id), + includes=sorted(includes))) diff --git a/generator/sbpg/targets/resources/sbp_message_traits_template.h b/generator/sbpg/targets/resources/sbp_message_traits_template.h new file mode 100644 index 0000000000..b01c78317d --- /dev/null +++ b/generator/sbpg/targets/resources/sbp_message_traits_template.h @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2019 Swift Navigation Inc. + * Contact: Swift Navigation + * + * This source is subject to the license found in the file 'LICENSE' which must + * be be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef SBP_CPP_MESSAGE_TRAITS_H +#define SBP_CPP_MESSAGE_TRAITS_H + +((*- for i in includes *)) +#include +((*- endfor *)) + +namespace sbp { + +/** + * Type traits containing meta-information for each SBP message type. + * + * These are only meant to be used by the C++ library at compile time. + * These are automatically generated, DO NOT EDIT. + */ +template +struct MessageTraits; + +((* for m in msgs *)) +((*- if m.fields *)) +template<> +struct MessageTraits<(((m.identifier|convert)))> { + static constexpr u16 id = (((m.sbp_id))); +}; +((* endif *)) +((* endfor *)) + + +} // namespace sbp + +#endif //SBP_CPP_MESSAGE_TRAITS_H From 73e715929647360d96c2f761c662ccb33a8265b9 Mon Sep 17 00:00:00 2001 From: Joseph Angelo Date: Tue, 22 Oct 2019 13:13:49 -0700 Subject: [PATCH 2/2] Added a C++ example program --- c/example/cpp_example/CMakeLists.txt | 16 ++++++ c/example/cpp_example/README.md | 49 +++++++++++++++++ c/example/cpp_example/cpp_example.cc | 80 ++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 c/example/cpp_example/CMakeLists.txt create mode 100644 c/example/cpp_example/README.md create mode 100644 c/example/cpp_example/cpp_example.cc diff --git a/c/example/cpp_example/CMakeLists.txt b/c/example/cpp_example/CMakeLists.txt new file mode 100644 index 0000000000..ea87966564 --- /dev/null +++ b/c/example/cpp_example/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8.9) +project(libsbp_cpp_example) + +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=c++11 ${CMAKE_CXX_FLAGS}") + +add_executable(libsbp_cpp_example cpp_example.cc) + +find_package(PkgConfig) + +link_directories("/usr/local/lib/") +include_directories("/usr/local/include/") + +target_link_libraries(libsbp_cpp_example sbp) diff --git a/c/example/cpp_example/README.md b/c/example/cpp_example/README.md new file mode 100644 index 0000000000..14c459d389 --- /dev/null +++ b/c/example/cpp_example/README.md @@ -0,0 +1,49 @@ +## Example of using the C++ classes for libsbp + +This example demonstrates parsing SBP from a file using the C++ classes + +## Requirements +On Debian-based systems (including Ubuntu 12.10 or later) you can get all +the requirements with: + +```shell +sudo apt-get install build-essential pkg-config cmake +``` + +On mac: + +```shell +brew install cmake +``` + +On other systems, you can obtain CMake from your operating system +package manager or from http://www.cmake.org/. + +## Installation + +Once you have the dependencies installed, create a build directory where the example will be built: + +```shell +mkdir build +cd build +``` + +Then invoke CMake to configure the build, and then build, + +```shell +cmake ../ +make +``` + +## Usage + +```shell +./libsbp_cpp_example +usage: ./libsbp_cpp_example [filename.sbp] +``` + +## LICENSE + +Copyright © 2019 Swift Navigation + +Distributed under LGPLv3.0. diff --git a/c/example/cpp_example/cpp_example.cc b/c/example/cpp_example/cpp_example.cc new file mode 100644 index 0000000000..7909406128 --- /dev/null +++ b/c/example/cpp_example/cpp_example.cc @@ -0,0 +1,80 @@ +#include +#include + +#include +#include + +void usage(char *prog_name) { + fprintf(stderr, "usage: %s [filename]\n", prog_name); +} + +class SbpFileReader : public sbp::IReader { + public: + SbpFileReader(const char *file_path) : file_stream_(file_path, std::ios::binary | std::ios_base::in) { } + + bool is_open() const { return file_stream_.is_open(); } + bool eof() const { return file_stream_.eof(); } + + s32 read(u8 *buffer, u32 buffer_length) override { + auto start_index = file_stream_.tellg(); + if (start_index == -1) { + return -1; + } + file_stream_.read(reinterpret_cast(buffer), buffer_length); + auto end_index = file_stream_.tellg(); + if (end_index == -1 || file_stream_.fail()) { + return -1; + } + + return static_cast(end_index - start_index); + } + + private: + std::ifstream file_stream_; +}; + +class ECEFHandler : private sbp::MessageHandler { + public: + ECEFHandler(sbp::State *state) : sbp::MessageHandler(state) { + } + + void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const msg_gps_time_t& msg) { + (void)sender_id; + (void)message_length; + std::cout << "Received new GPS_TME message with WN = " << msg.wn << ", TOW = " << msg.tow << "\n"; + } + + void handle_sbp_msg(uint16_t sender_id, uint8_t message_length, const msg_pos_ecef_t& msg) { + (void)sender_id; + (void)message_length; + std::cout << "Received new POS_ECEF message with TOW = " << msg.tow; + std::cout << ", (X,Y,Z) = (" << msg.x << "," << msg.y << "," << msg.z << ")\n"; + } +}; + +int main(int argc, char **argv) +{ + if (argc <= 1) { + usage(argv[0]); + exit(EXIT_FAILURE); + } + + const char *file_path = argv[1]; + + SbpFileReader reader(file_path); + if (!reader.is_open()) { + usage(argv[0]); + exit(EXIT_FAILURE); + } + + sbp::State s; + ECEFHandler handler(&s); + + s.set_reader(&reader); + + while(!reader.eof()) { + s.process(); + } + + return 0; +}