Goby3 3.6.1
2026.09.15
Loading...
Searching...
No Matches
application.h
Go to the documentation of this file.
1// Copyright 2025-2026:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Goby Underwater Autonomy Project Libraries
9// ("The Goby Libraries").
10//
11// The Goby Libraries are free software: you can redistribute them and/or modify
12// them under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// The Goby Libraries are distributed in the hope that they will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with Goby. If not, see <http://www.gnu.org/licenses/>.
23
24#include <jlcxx/functions.hpp>
25#include <jlcxx/jlcxx.hpp>
26
32#include "goby/time.h"
33
34namespace goby
35{
36namespace middleware
37{
38namespace julia
39{
40// the language-neutral types live in goby::middleware::languages; these aliases keep the names
41// used by the generated Julia glue code (goby::middleware::julia::Identifier, etc.) working
45
46template <typename AppBase> class Application : public AppBase
47{
48 public:
49 Application() { loop_ = std::make_unique<jlcxx::JuliaFunction>("cxx_loop", "Goby"); }
50 void loop() override { (*loop_)(); }
51
52 private:
53 std::unique_ptr<jlcxx::JuliaFunction> loop_;
54};
55
56template <typename App> class ApplicationWrapper
57{
58 public:
59 ApplicationWrapper(std::string config)
60 {
61 typename App::ConfigType cfg;
62 google::protobuf::TextFormat::Parser parser;
63 goby::util::FlexOStreamErrorCollector error_collector(config);
64 parser.RecordErrorsTo(&error_collector);
65 parser.AllowPartialMessage(false);
66 parser.ParseFromString(config, &cfg);
67
68 App::app_cfg_.reset(new typename App::ConfigType(cfg));
69 App::app3_base_configuration_.reset(new goby::middleware::protobuf::AppConfig(cfg.app()));
70
71 goby::middleware::detail::configure_simulation_time(*App::app3_base_configuration_);
72
73 app_ptr_.reset(new App);
74 }
75
76 void run() { app_ptr_->__run(); }
77
78 ApplicationWrapper& interprocess() { return *this; }
79
80 void publish(PubSubLayer layer, std::string type_name, int scheme, std::string group,
81 const std::vector<std::uint8_t>& bytes)
82 {
83 app_ptr_->publish(Identifier{layer, type_name, scheme, group}, bytes);
84 }
85
86 void subscribe(PubSubLayer layer, std::string type_name, int scheme, std::string group,
87 std::string func, std::string module)
88 {
89 app_ptr_->subscribe(Identifier{layer, type_name, scheme, group}, func, module);
90 }
91
92 void set_loop_frequency_hertz(double freq) { app_ptr_->set_loop_frequency_hertz(freq); }
93
94 std::vector<std::uint8_t> cfg_serialized()
95 {
96 std::vector<std::uint8_t> v(app_ptr_->app_cfg().ByteSizeLong());
97 app_ptr_->app_cfg().SerializeToArray(&v[0], v.size());
98 return v;
99 }
100
101 private:
102 std::unique_ptr<App> app_ptr_;
103};
104
105template <typename App>
106inline void define_julia_module(jlcxx::Module& types, const std::string& app_name)
107{
108 types.add_bits<PubSubLayer>("PubSubLayer", jlcxx::julia_type("CppEnum"));
109 types.set_const("INTERTHREAD", PubSubLayer::INTERTHREAD);
110 types.set_const("INTERPROCESS", PubSubLayer::INTERPROCESS);
111 types.set_const("INTERMODULE", PubSubLayer::INTERMODULE);
112
113 types.add_bits<MarshallingScheme::MarshallingSchemeEnum>("MarshallingScheme",
114 jlcxx::julia_type("CppEnum"));
115 types.set_const("NULL_SCHEME", MarshallingScheme::NULL_SCHEME);
116 types.set_const("PROTOBUF", MarshallingScheme::PROTOBUF);
117 types.set_const("JSON", MarshallingScheme::JSON);
118
119 types.template add_type<ApplicationWrapper<App>>(app_name)
120 .template constructor<std::string>()
121 .method("cxx_run", &ApplicationWrapper<App>::run)
122 .method("cxx_publish", &ApplicationWrapper<App>::publish)
123 .method("cxx_subscribe", &ApplicationWrapper<App>::subscribe)
124 .method("cxx_set_loop_frequency_hertz", &ApplicationWrapper<App>::set_loop_frequency_hertz)
125 .method("cxx_cfg_serialized", &ApplicationWrapper<App>::cfg_serialized);
126}
127
128} // namespace julia
129} // namespace middleware
130} // namespace goby
131
132// Macros for use by the autogenerated code to define the C++ side of the pub/sub setup
133//
134// GROUP_KEY is the interface.yml expression for GROUP as a string, which is the only name Julia
135// has for the group; a group's runtime name need not be its C++ variable name.
136#define GOBY_JULIA_IF_PUBLICATION(SCHEME, LAYER_ENUM, LAYER_FUNCTION, GROUP, GROUP_KEY, TYPE) \
137 if (id == goby::middleware::julia::Identifier{ \
138 goby::middleware::julia::PubSubLayer::LAYER_ENUM, TYPE::descriptor()->name(), \
139 goby::middleware::MarshallingScheme::SCHEME, GROUP_KEY}) \
140 { \
141 decltype(bytes.end()) actual_end; \
142 auto msg = goby::middleware::SerializerParserHelper< \
143 TYPE, goby::middleware::MarshallingScheme::SCHEME>::parse(bytes.begin(), bytes.end(), \
144 actual_end); \
145 LAYER_FUNCTION().publish<GROUP>(msg); \
146 return; \
147 }
148
149#define GOBY_JULIA_IF_SUBSCRIPTION(SCHEME, LAYER_ENUM, LAYER_FUNCTION, GROUP, GROUP_KEY, TYPE) \
150 if (id == goby::middleware::julia::Identifier{ \
151 goby::middleware::julia::PubSubLayer::LAYER_ENUM, TYPE::descriptor()->name(), \
152 goby::middleware::MarshallingScheme::SCHEME, GROUP_KEY}) \
153 { \
154 LAYER_FUNCTION().subscribe<GROUP>( \
155 [=](const TYPE& pb) \
156 { \
157 std::vector<std::uint8_t> bytes = goby::middleware::julia::serialize_uint8< \
158 TYPE, goby::middleware::MarshallingScheme::SCHEME>(pb); \
159 jlcxx::JuliaFunction cb(func, module); \
160 cb(id.layer, id.type_name, id.scheme, id.group, bytes); \
161 }); \
162 return; \
163 }
164
165#define GOBY_JULIA_FAIL(PUBLISH_OR_SUBSCRIBE) \
166 goby::glog.is_die() && \
167 goby::glog << PUBLISH_OR_SUBSCRIBE " not defined for these parameters: [" << id \
168 << "]. Please include in interfaces.yml and re-generate to include them." \
169 << std::endl;
170
171// used to stringify application name
172#define GOBY_JULIA_QUOTE(name) #name
173#define GOBY_JULIA_DEFINE_MODULE(APPLICATION_NAME) \
174 JLCXX_MODULE define_julia_module(jlcxx::Module& types) \
175 { \
176 goby::middleware::julia::define_julia_module<APPLICATION_NAME>( \
177 types, GOBY_JULIA_QUOTE(APPLICATION_NAME)); \
178 }
void subscribe(PubSubLayer layer, std::string type_name, int scheme, std::string group, std::string func, std::string module)
Definition application.h:86
void publish(PubSubLayer layer, std::string type_name, int scheme, std::string group, const std::vector< std::uint8_t > &bytes)
Definition application.h:80
std::vector< std::uint8_t > cfg_serialized()
Definition application.h:94
goby::util::logger::GroupSetter group(std::string n)
void configure_simulation_time(const protobuf::AppConfig &app_cfg)
Applies the simulation time settings from an application configuration to goby::time::SimulatorSettin...
void define_julia_module(jlcxx::Module &types, const std::string &app_name)
std::vector< std::uint8_t > serialize_uint8(const DataType &msg)
Marshals a message using the given scheme, returning the bytes to hand to the bound language.
Definition interface.h:100
PubSubLayer
The publish/subscribe layer used for a given publication or subscription.
Definition interface.h:52
constexpr int scheme()
Placeholder to provide an interface for the scheme() function family.
Definition cstr.h:65
The global namespace for the Goby project.
MarshallingSchemeEnum
Marshalilng schemes implemented in Goby.
Definition interface.h:49
Fully identifies a publication or subscription crossing the language boundary.
Definition interface.h:76