DCCL v4
dynamic_protobuf.cpp
1 // Copyright 2019-2023:
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 Dynamic Compact Control Language Library
9 // ("DCCL").
10 //
11 // DCCL is free software: you can redistribute it and/or modify
12 // it 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 // DCCL is distributed in the hope that it 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 DCCL. If not, see <http://www.gnu.org/licenses/>.
23 #include "../../dynamic_protobuf_manager.h"
24 #include <cassert>
25 #include <dlfcn.h>
26 #include <google/protobuf/descriptor.pb.h>
27 #include <google/protobuf/text_format.h>
28 #include <iostream>
29 
30 #include "test_a.pb.h"
31 
32 int main(int argc, char* argv[])
33 {
34  if (argc != 2)
35  {
36  std::cerr << "Usage: " << argv[0] << " /path/to/libtest_dyn_protobuf" << std::endl;
37  exit(1);
38  }
39 
40  void* dl_handle = dlopen(argv[1], RTLD_LAZY);
41 
42  if (!dl_handle)
43  {
44  std::cerr << "Failed to open libtest_dyn_protobuf" SHARED_LIBRARY_SUFFIX
45  << ", error: " << dlerror() << std::endl;
46  exit(1);
47  }
48 
49  std::shared_ptr<google::protobuf::SimpleDescriptorDatabase> simple_database(
50  new google::protobuf::SimpleDescriptorDatabase);
52 
53  {
54  // testing compiled in
55  std::shared_ptr<google::protobuf::Message> adyn_msg =
57 
58  std::cout << adyn_msg->GetDescriptor()->DebugString() << std::endl;
59 
60  // testing dlopen'd
61  std::shared_ptr<google::protobuf::Message> bdyn_msg =
63 
64  std::cout << bdyn_msg->GetDescriptor()->DebugString() << std::endl;
65 
66  // test non-existent
67  try
68  {
69  std::shared_ptr<google::protobuf::Message> cdyn_msg =
71  // should throw
72  assert(false);
73  }
74  catch (std::exception& e)
75  {
76  // expected
77  }
78 
79  // test dynamically loaded
80  google::protobuf::FileDescriptorProto d_proto;
81  std::string d_proto_str = "name: \"goby/test/util/dynamic_protobuf/test_d.proto\" "
82  "message_type { name: \"D\" field { name: \"d1\" "
83  "number: 1 label: LABEL_REQUIRED type: TYPE_DOUBLE } } ";
84 
85  google::protobuf::TextFormat::ParseFromString(d_proto_str, &d_proto);
87 
88  std::shared_ptr<google::protobuf::Message> ddyn_msg =
90 
91  std::cout << ddyn_msg->GetDescriptor()->DebugString() << std::endl;
92 
93  // test dynamically via separate database
94  google::protobuf::FileDescriptorProto e_proto;
95  std::string e_proto_str = "name: \"goby/test/util/dynamic_protobuf/test_e.proto\" "
96  "message_type { name: \"E\" field { name: \"e1\" "
97  "number: 1 label: LABEL_REQUIRED type: TYPE_DOUBLE } } ";
98 
99  google::protobuf::TextFormat::ParseFromString(e_proto_str, &e_proto);
100 
101  simple_database->Add(e_proto);
102 
103  std::shared_ptr<google::protobuf::Message> edyn_msg =
105  std::cout << edyn_msg->GetDescriptor()->DebugString() << std::endl;
106 
107  std::cout << "all tests passed" << std::endl;
108  }
109 
110  dccl::DynamicProtobufManager::protobuf_shutdown();
111 
112  dlclose(dl_handle);
113  return 0;
114 }
dccl::DynamicProtobufManager::add_protobuf_file
static const google::protobuf::FileDescriptor * add_protobuf_file(const google::protobuf::FileDescriptorProto &proto)
Add a protobuf file defined in a google::protobuf::FileDescriptorProto.
Definition: dynamic_protobuf_manager.cpp:124
dccl::DynamicProtobufManager::add_database
static void add_database(std::shared_ptr< google::protobuf::DescriptorDatabase > database)
Add a Google Protobuf DescriptorDatabase to the set of databases searched for Message Descriptors.
Definition: dynamic_protobuf_manager.cpp:78
dccl::DynamicProtobufManager::new_protobuf_message
static GoogleProtobufMessagePointer new_protobuf_message(const std::string &protobuf_type_name, bool user_pool_first=false)
Create a new (empty) Google Protobuf message of a given type by name.
Definition: dynamic_protobuf_manager.h:76