Example: serialization_variant_example
C++ example source code:
/* +------------------------------------------------------------------------+ | Mobile Robot Programming Toolkit (MRPT) | | https://www.mrpt.org/ | | | | Copyright (c) 2005-2023, Individual contributors, see AUTHORS file | | See: https://www.mrpt.org/Authors - All rights reserved. | | Released under BSD License. See: https://www.mrpt.org/License | +------------------------------------------------------------------------+ */ #include <mrpt/io/CPipe.h> #include <mrpt/poses/CPose2D.h> #include <mrpt/poses/CPose3D.h> #include <mrpt/serialization/CArchive.h> #include <chrono> #include <iostream> #include <thread> using namespace mrpt; using namespace mrpt::poses; using namespace mrpt::system; using namespace mrpt::io; using namespace mrpt::serialization; using namespace std; void thread_reader(CPipeReadEndPoint& read_pipe) { try { std::cout << "[thread_reader ID:" << std::this_thread::get_id() << "] Started." << std::endl; // Simple read commands: size_t len = 0; char buf[100]; read_pipe.Read(&len, sizeof(len)); read_pipe.Read(buf, len); buf[len] = 0; cout << "RX: " << buf << endl; // Read MRPT object from a pipe: // *Note*: If the object class is known in advance, one can avoid smart // pointers with ReadObject(&existingObj) auto arch = archiveFrom(read_pipe); #if !defined(HAS_BROKEN_CLANG_STD_VISIT) auto doprint = [](auto& pose) { cout << "RX pose: " << pose << endl; }; auto var = arch.ReadVariant<mrpt::poses::CPose2D, mrpt::poses::CPose3D>(); std::visit(doprint, var); var = arch.ReadVariant<mrpt::poses::CPose2D, mrpt::poses::CPose3D>(); std::visit(doprint, var); #else std::cout << "Code disabled for clang due to variant bug. See: " "https://stackoverflow.com/a/46507150/1631514\n"; #endif printf("[thread_reader] Finished.\n"); } catch (const std::exception& e) { cerr << e.what() << endl; } } void thread_writer(CPipeWriteEndPoint& write_pipe) { try { std::cout << "[thread_writer ID:" << std::this_thread::get_id() << "] Started." << std::endl; // Simple write commands: const char* str = "Hello world!"; size_t len = strlen(str); write_pipe.Write(&len, sizeof(len)); write_pipe.Write(str, len); // Send MRPT objects: mrpt::poses::CPose3D pose1(1, 2, 3, 1.57, 3.14, 0); mrpt::poses::CPose2D pose2(1.0, 2.0, 3.1415); #if !defined(HAS_BROKEN_CLANG_STD_VISIT) std::variant<mrpt::poses::CPose3D, mrpt::poses::CPose2D> var1( std::move(pose1)); std::variant<mrpt::poses::CPose3D, mrpt::poses::CPose2D> var2( std::move(pose2)); auto arch = archiveFrom(write_pipe); arch.WriteVariant(var1); arch.WriteVariant(var2); #endif printf("[thread_writer] Finished.\n"); } catch (const std::exception& e) { cerr << e.what() << endl; } } // ------------------------------------------------------ // ThreadsTest // ------------------------------------------------------ void ThreadsTest() { // Create a pipe: std::unique_ptr<CPipeReadEndPoint> read_pipe; std::unique_ptr<CPipeWriteEndPoint> write_pipe; CPipe::createPipe(read_pipe, write_pipe); // And send the two end-points to two threads: std::thread hT1(thread_reader, std::ref(*read_pipe)); std::thread hT2(thread_writer, std::ref(*write_pipe)); using namespace std::chrono_literals; std::this_thread::sleep_for(10ms); // Wait for the threads to end. hT2.join(); // We need to close this to ensure the pipe gets flushed // Remember Unix uses buffered io // write_pipe.reset(); hT1.join(); } // ------------------------------------------------------ // MAIN // ------------------------------------------------------ int main() { try { ThreadsTest(); return 0; } catch (const std::exception& e) { std::cerr << "MRPT error: " << mrpt::exception_to_str(e) << std::endl; return -1; } }