Git Product home page Git Product logo

cyclonedds-cxx's Introduction

C++ binding for Eclipse Cyclone DDS

An implementation of the ISO/IEC C++ PSM, or simply put, a C++ binding for Eclipse Cyclone DDS. Cyclone DDS is developed completely in the open as an Eclipse IoT project (see eclipse-cyclone-dds) with a growing list of adopters (if you're one of them, please add your logo). It is a tier-1 middleware for the Robot Operating System ROS 2.

Build Status Coverity Status Codecov License License

Getting Started

Building the Eclipse Cyclone DDS C++ binding

In order to build the C++ binding for Cyclone DDS you need a Linux, Mac or Windows 10 machine (or, with some caveats, a *BSD, OpenIndiana one) with the following installed on your host:

  • C and C++ compilers (most commonly GCC on Linux, Visual Studio on Windows, Xcode on macOS);
  • Git version control system;
  • CMake, version 3.16 or later;
  • Eclipse Cyclone DDS

Eclipse Cyclone DDS has dependencies of its own, most notably Bison. To build and install it, please consult the build instructions. Ensure the project is installed into a location convenient for you by specifying CMAKE_INSTALL_PREFIX.

To obtain the C++ binding for Cyclone DDS, do

$ git clone https://github.com/eclipse-cyclonedds/cyclonedds-cxx.git
$ cd cyclonedds-cxx
$ mkdir build

Depending on whether you want to develop applications using the C++ binding for Cyclone DDS or contribute to it you can follow different procedures.

Build configuration

There are some configuration options specified using CMake defines in addition to the standard options like CMAKE_BUILD_TYPE:

  • -DBUILD_DDSLIB=OFF: to disable DDS lib build, useful in crosscompiling scenarios where you only need the generator and use the DDS lib from another build.
  • -DBUILD_IDLLIB=OFF: to disable IDL preprocessor lib build
  • -DBUILD_DOCS=ON: to build the documentation
  • -DBUILD_TESTING=ON: to build the testing tree
  • -DBUILD_EXAMPLES=ON: to build examples
  • -DENABLE_LEGACY=YES: to enable legacy c++11 mode, adds boost as dependency (otherwise it uses c++17)
  • -DENABLE_ICEORYX=YES: to enable Iceoryx tests
  • -DENABLE_TYPELIB=YES: to enable type library support
  • -DENABLE_TOPIC_DISCOVERY=YES: to enable topic discovery support
  • -DENABLE_COVERAGE=YES: to enable coverage build
  • -DENABLE_QOS_PROVIDER=YES: to enable qos provider support

For application developers

To build and install the required libraries needed to develop your own applications using the C++ binding for Cyclone DDS requires a few simple steps. There are some small differences between Linux and macOS on the one hand, and Windows on the other. For Linux or macOS:

$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=<install-location> \
        -DCMAKE_PREFIX_PATH="<cyclonedds-install-location>" \
        ..
$ cmake --build .

and for Windows:

$ cd build
$ cmake -G "<generator-name>" \
        -DCMAKE_INSTALL_PREFIX=<install-location> \
        -DCMAKE_PREFIX_PATH="<cyclonedds-install-location>" \
        ..
$ cmake --build .

where you should replace <install-location> by the directory under which you would like to install the C++ binding for Cyclone DDS and <generator-name> by one of the ways CMake generators offer for generating build files. For example, "Visual Studio 15 2017 Win64" would target a 64-bit build using Visual Studio 2017.

To install it after a successful build, do:

$ cmake --build . --target install

Which will copy everything to:

  • <install-location>/lib
  • <install-location>/bin
  • <install-location>/include/ddsc
  • <install-location>/share/CycloneDDS-CXX

Depending on the installation location you may need administrator privileges.

At this point you are ready to use Eclipse Cyclone DDS in your own projects.

Note that the default build type is a release build with debug information included (RelWithDebInfo), which is generally the most convenient type of build to use from applications because of a good mix between performance and still being able to debug things. If you'd rather have a Debug or pure Release build, set CMAKE_BUILD_TYPE accordingly.

Contributing to Eclipse Cyclone DDS

We very much welcome all contributions to the project, whether that is questions, examples, bug fixes, enhancements or improvements to the documentation, or anything else really. When considering contributing code, it might be good to know that build configurations for Travis CI and AppVeyor are present in the repository and that there is a test suite using CTest and Google Test that can be built locally if desired. To build it, set the cmake variable BUILD_TESTING to on when configuring, e.g.:

$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ..
$ cmake --build .
$ ctest

Such a build requires the presence of Google Test. You need to install this yourself.

Documentation

The documentation is still rather limited, and at the moment only available in the sources (in the form of restructured text files in docs and Doxygen comments in the header files). The intent is to automate the process of building the documentation and have them available in more convenient formats and in the usual locations.

Building and Running the HelloWorld Example

We will show you how to build and run an example program that illustrates the necessary steps to setup DCPS entities. The examples are built automatically when you build the C++ language binding for Cyclone DDS, so you don't need to follow these steps to be able to run the program, it is merely to illustrate the process.

$ mkdir helloworld
$ cd helloworld
$ cmake <install-location>/share/CycloneDDS-CXX/examples/helloworld
$ cmake --build .

On one terminal start the application that will be responding to messages:

$ ./ddscxxHelloWorldSubscriber

On another terminal, start the application that will be sending the messages:

$ ./ddscxxHelloWorldPublisher

Trademarks

  • "Eclipse Cyclone DDS" and "Cyclone DDS" are trademarks of the Eclipse Foundation.
  • "DDS" is a trademark of the Object Management Group, Inc.
  • "ROS" is a trademark of Open Source Robotics Foundation, Inc.

License

This project contains 2 types of license: Apache2 and Eclipse Public License / Eclipse Distribution License

  • The Apache2 license located in src/ddscxx/include/dds is for all files under src/ddscxx/include/dds except the details directories
  • Eclipse Public License / Eclipse Distribution License is valid for all other files.

cyclonedds-cxx's People

Contributors

clunietp avatar dkroenke avatar dpotman avatar e-hndrks avatar eboasson avatar elfenpiff avatar erikatapex avatar ichernev avatar javiersorianoruiz avatar k0ekk0ek avatar kischy avatar kurtuluso avatar matthiaskillat avatar mtudan avatar noxpardalis avatar petercadogan avatar pro avatar reicheratwork avatar seanyu81 avatar stan-guer avatar stefansli avatar sumanth-nirmal avatar t0ny-peng avatar thijsmie avatar thijssassen avatar trittsv avatar wadehunk avatar zephod77 avatar zijian-teng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cyclonedds-cxx's Issues

IDLCXX generated code doesn't use unique include guards

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone Version

Observed result or behaviour:

There is an issue with include guards in the generated code, The following scenario should explain the problem.
If we have the following IDL files, with the same name but in different paths

  1. Duration.idl in path foo1/bar1/msg/
  2. Duration.idl in path foo2/bar2/msg/

The generated header for both the IDL's has the same include guard as below

#ifndef DDSCXX_DURATION__HPP
#define DDSCXX_DURATION__HPP
...
#endif /* DDSCXX_DURATION__HPP */

If the user code wants to use both the Duration.idls above and include them in the code as below

#include <foo1/bar1/msg/Duration.hpp>
#include <foo2/bar2/msg/Duration.hpp>
...

because of the include guards, it will only find the definitions for one file, and can't find the definitions for the other!

Expected result or behaviour:

The include guards for the generated headers should be unique. It can probably also take the namespace into account instead of just using the name of the IDL, or use some hash of the file contents along with the name of the IDL.

Serialization is incorrect with sequences

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behaviour:

The serialization/de-serialization doesn't seem to happen correctly with sequences

Detailed reproducer

When using the following nested IDL files

in the code as below:

std::shared_ptr<test_msgs::msg::dds_::basic_types>
get_msg_basic_types()
{
  auto msg = std::make_shared<test_msgs::msg::dds_::basic_types>();
  {
    msg->bool_value_(false);
    msg->byte_value_(0);
    msg->char_value_(0);
    msg->float32_value_(0.0f);
    msg->float64_value_(0);
    msg->int8_value_(0);
    msg->uint8_value_(0);
    msg->int16_value_(0);
    msg->uint16_value_(0);
    msg->int32_value_(0);
    msg->uint32_value_(0);
    msg->int64_value_(0);
    msg->uint64_value_(0);
  }
  return msg;
}

std::shared_ptr<test_msgs::msg::dds_::unbounded_seq>
get_msg_unbounded_sequences()
{
  auto basic_types_msgs = get_msg_basic_types();
  auto msg = std::make_shared<test_msgs::msg::dds_::unbounded_seq>();
  {
    msg->bool_values_({true});
    msg->byte_values_({0xff});
    msg->char_values_({255});
    msg->float32_values_({1.125f});
    msg->float64_values_({1.125});
    msg->int8_values_({(std::numeric_limits<int8_t>::max)()});
    msg->uint8_values_({(std::numeric_limits<uint8_t>::max)()});
    msg->int16_values_({(std::numeric_limits<int16_t>::max)()});
    msg->uint16_values_({(std::numeric_limits<uint16_t>::max)()});
    msg->int32_values_({(std::numeric_limits<int32_t>::max)()});
    msg->uint32_values_({(std::numeric_limits<uint32_t>::max)()});
    msg->int64_values_({(std::numeric_limits<int64_t>::max)()});
    msg->uint64_values_({(std::numeric_limits<uint64_t>::max)()});
    msg->string_values_({{"max value"}});
    msg->basic_types_values_({*basic_types_msgs});
    msg->alignment_check_(1);
  }
  return msg;
}

TEST(tooch, serialize_deserialize)
{
  using DDSType = test_msgs::msg::dds_::unbounded_seq;

  // data
  auto msg = get_msg_unbounded_sequences();

  org::eclipse::cyclonedds::core::cdr::basic_cdr_stream cdr_streamer;
  uint8_t buffer[2048];
  // fill the buffer to some non-zero to see the effect
  std::memset(buffer, 0xaa, sizeof(buffer));
  {
    //serialize
    cdr_streamer.set_buffer(buffer);
    org::eclipse::cyclonedds::core::cdr::write(cdr_streamer, *msg);
    EXPECT_FALSE(cdr_streamer.abort_status());
  }

  DDSType deserialized_msg{};
  EXPECT_NE(*msg, deserialized_msg);
  {
    //deserialize
    cdr_streamer.set_buffer(buffer);
    org::eclipse::cyclonedds::core::cdr::read(cdr_streamer, deserialized_msg);
    EXPECT_FALSE(cdr_streamer.abort_status());
  }
  EXPECT_EQ(*msg, deserialized_msg);
}

In the code above, I try to serialize the type, then deserialize it back and compare it with the original type, which should ideally match with the original type, but it fails with the below error:

Expected equality of these values:
  *msg
    Which is: 784-byte object <A0-54 68-94 A9-55 00-00 00-00 00-00 00-00 00-00 A0-54 68-94 A9-55 00-00 01-00 00-00 00-00 00-00 A8-54 68-94 A9-55 00-00 C0-54 68-94 A9-55 00-00 C1-54 68-94 A9-55 00-00 C1-54 68-94 A9-55 00-00 ... 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 01-00 00-00 00-00 00-00>
  deserialized_msg
    Which is: 784-byte object <90-D1 61-94 A9-55 00-00 00-00 00-00 00-00 00-00 90-D1 61-94 A9-55 00-00 01-00 00-00 00-00 00-00 98-D1 61-94 A9-55 00-00 70-D1 61-94 A9-55 00-00 71-D1 61-94 A9-55 00-00 71-D1 61-94 A9-55 00-00 ... 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 01-00 00-00 00-00 00-00>

Expected result or behaviour:

The serialization/deserialization should work correctly with all types of sequences

<Package>Config.cmake files not being installed

The cmake files required for find_package are not being generated/installed.

To reproduce:
$ cmake -Bbuild . -DCMAKE_PREFIX_PATH=$PREFIX_PATH -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR
$ cd ./build
$ cmake --build . --target install -j8

Expected:
CycloneDDS-CXXConfig.cmake files are installed in $INSTALL_DIR/lib/cmake/CycloneDDS-CXX

Actual:
Files do not exist in the install directory.

Generating with VS Studio 2017 fails

If I use generate on the current state of the master branch with
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX="D:/EclipseCylconeDDS_newer/cyclonedds-cxx/install" -DCMAKE_PREFIX_PATH="D:/EclipseCylconeDDS_newer/cyclonedds/install" -DBUILD_EXAMPLES=OFF ..

it fails with the following error

CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
  Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?

What am I doing wrong here?

Compilation Error with generated code from idlcxx

CycloneDDS version: eclipse-cyclonedds/cyclonedds@7bc4326
CYcloneDDS-CXX version: 0add050

When using the idlcxx generator in iceoryx, there are some compile errors with the generated code:

In file included from iceoryx/iceoryx_dds/include/iceoryx_dds/dds/cyclone_data_writer.hpp:23,
                 from iceoryx/iceoryx_dds/source/iceoryx_dds/dds/cyclone_data_writer.cpp:18:
iceoryx/build/iceoryx_dds_messages/Mempool.hpp: In static member function ‘static ddsi_sertype* org::eclipse::cyclonedds::topic::TopicTraits<Mempool::Chunk>::getSerType()’:
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:72:20: error: ‘ddscxx_sertype’ does not name a type; did you mean ‘ddsi_sertype’?
   72 |     auto *st = new ddscxx_sertype<::Mempool::Chunk>();
      |                    ^~~~~~~~~~~~~~
      |                    ddsi_sertype
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:72:51: error: expected primary-expression before ‘>’ token
   72 |     auto *st = new ddscxx_sertype<::Mempool::Chunk>();
      |                                                   ^
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:72:53: error: expected primary-expression before ‘)’ token
   72 |     auto *st = new ddscxx_sertype<::Mempool::Chunk>();
      |                                                     ^
iceoryx/build/iceoryx_dds_messages/Mempool.hpp: At global scope:
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:96:8: error: ‘topic_type_name’ is not a class template
   96 | struct topic_type_name<::Mempool::Chunk>
      |        ^~~~~~~~~~~~~~~
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:97:1: error: explicit specialization of non-template ‘dds::topic::topic_type_name’
   97 | {
      | ^
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:109:1: error: expected constructor, destructor, or type conversion before ‘namespace’
  109 | namespace org{
      | ^~~~~~~~~
In file included from iceoryx/build/dependencies/install/include/ddscxx/dds/topic/TTopicDescription.hpp:23,
                 from iceoryx/build/dependencies/install/include/ddscxx/dds/topic/detail/TTopicDescriptionImpl.hpp:22,
                 from iceoryx/build/dependencies/install/include/ddscxx/dds/topic/detail/TopicDescription.hpp:21,
                 from iceoryx/build/dependencies/install/include/ddscxx/dds/topic/TopicDescription.hpp:22,
                 from iceoryx/build/dependencies/install/include/ddscxx/dds/topic/ddstopic.hpp:22,
                 from iceoryx/build/dependencies/install/include/ddscxx/dds/dds.hpp:35,
                 from iceoryx/iceoryx_dds/include/iceoryx_dds/dds/cyclone_data_writer.hpp:24,
                 from iceoryx/iceoryx_dds/source/iceoryx_dds/dds/cyclone_data_writer.cpp:18:
iceoryx/build/dependencies/install/include/ddscxx/dds/topic/TopicTraits.hpp:46:8: error: ‘dds::topic::topic_type_name’ is not a template
   46 | struct topic_type_name
      |        ^~~~~~~~~~~~~~~
In file included from iceoryx/iceoryx_dds/include/iceoryx_dds/dds/cyclone_data_writer.hpp:23,
                 from iceoryx/iceoryx_dds/source/iceoryx_dds/dds/cyclone_data_writer.cpp:18:
iceoryx/build/iceoryx_dds_messages/Mempool.hpp:96:8: note: previous declaration here
   96 | struct topic_type_name<::Mempool::Chunk>

This error comes up when trying to use the generated Code from idlcxx.

The idl file for it is here: https://github.com/ApexAI/iceoryx/blob/iox-%23736-update-cyclonedds-to-idlcxx/iceoryx_dds/msg/Mempool.idl

The CMake processing for generating the code: https://github.com/ApexAI/iceoryx/blob/iox-%23736-update-cyclonedds-to-idlcxx/iceoryx_dds/cmake/idlcxx-generate.cmake.in

And attached the generated file:
Mempool_generated.zip

Do you have maybe a hint for me what could be possibly wrong here?
The cyclone_data_writer hpp and cpp are only including the Mempool.hpp at that places.

IDL: enum and union code compilation issue

  • Ubuntu 20.04
  • g++ 9.3.0

The following IDL does not generate code that compiles (compiles with opensplice):

  enum e_type
  {
     EE_A,
     EE_L,
     EE_S1,
     EE_S2,
     EE_S3
  };

  union u_e_type switch (boolean)
  {
    // the value when present
    case TRUE : e_type value;
  };

Compilation output:

/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldDataSplDcps.cpp: In function ‘void __HelloWorldData_u_e_type__copyOut(const void*, void*)’:
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldDataSplDcps.cpp:83:56: error: no matching function for call to ‘HelloWorldData::u_e_type::value(HelloWorldData_e_type)’
   83 |         to->value((HelloWorldData_e_type)from->_u.value);
      |                                                        ^
In file included from /home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData_DCPS.hpp:6,
                 from /home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldDataSplDcps.cpp:2:
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData.h:239:32: note: candidate: ‘HelloWorldData::e_type HelloWorldData::u_e_type::value() const’
  239 |         HelloWorldData::e_type value() const
      |                                ^~~~~
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData.h:239:32: note:   candidate expects 0 arguments, 1 provided
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData.h:248:33: note: candidate: ‘HelloWorldData::e_type& HelloWorldData::u_e_type::value()’
  248 |         HelloWorldData::e_type& value()
      |                                 ^~~~~
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData.h:248:33: note:   candidate expects 0 arguments, 1 provided
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData.h:257:14: note: candidate: ‘void HelloWorldData::u_e_type::value(HelloWorldData::e_type)’
  257 |         void value(HelloWorldData::e_type val)
      |              ^~~~~
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldData.h:257:43: note:   no known conversion for argument 1 from ‘HelloWorldData_e_type’ to ‘HelloWorldData::e_type’
  257 |         void value(HelloWorldData::e_type val)
      |                    ~~~~~~~~~~~~~~~~~~~~~~~^~~
make[2]: *** [CMakeFiles/ddscxxHelloworldSubscriber.dir/build.make:124: CMakeFiles/ddscxxHelloworldSubscriber.dir/HelloWorldDataSplDcps.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:82: CMakeFiles/ddscxxHelloworldSubscriber.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

The primary difference between the two is that opensplice uses int32_t and cyclonedds uses enum.

This means that the following generated code:

to->value((HelloWorldData_e_type)from->_u.value);

should really be:

to->value((HelloWorldData::e_type)from->_u.value);

IDL: typedef causes problems with keyfield

Ubuntu 20.04

The following IDL works with opensplice but fails with the current C++ idl compiler of cyclonedds:

  enum e_type
  {
     EE_A,
     EE_L,
     EE_S1,
     EE_S2,
     EE_S3
  };

  typedef struct tag_Ident_T {
    long id;
    e_type idType;
  } Ident_T;

  struct Report_T {
    Ident_T    id;    //@key
    long       value;
  };
  #pragma keylist Report_T id.id id.idType value

Failure messages:

HelloWorldData.idl:34, keyfield id.id is either missing or unsupported
HelloWorldData.idl:34, keyfield id.idType is either missing or unsupported

The work around is to remove the typedef and tag_Ident_T. However I've too many definitions supplied to me for me to get away with making this change.

Convenience Function missing for dds::core::policy::Liveliness::Automatic?

There is a function with a const dds::core::Duration& lease_duration parameter for Liveliness ManualByParticipant and ManualByTopic.

template <typename D>
TLiveliness<D> TLiveliness<D>::ManualByParticipant(const dds::core::Duration& lease_duration)
{
    return TLiveliness(dds::core::policy::LivelinessKind::MANUAL_BY_PARTICIPANT, lease_duration);
}

template <typename D>
TLiveliness<D> TLiveliness<D>::ManualByTopic(const dds::core::Duration& lease_duration)
{
    return TLiveliness(dds::core::policy::LivelinessKind::MANUAL_BY_TOPIC, lease_duration);
}

For Liveliness Automatic I only found a parameterless function

template <typename D>
TLiveliness<D> TLiveliness<D>::Automatic()
{
    return TLiveliness(dds::core::policy::LivelinessKind::AUTOMATIC, dds::core::Duration::infinite());
}

Should'nt the function for Liveliness Automatic also have a parameter for the lease_duration? The OMG standard says for LIVELINESS::AUTOMATIC:

The infrastructure will automatically signal
liveliness for the DataWriters at least as
often as required by the lease_duration.

So the lease_duration is used with liveliness automatic.

Callback functions being called when constructor has not yet finished

Example:

dds::domain::DomainParticipant participant(org::eclipse::cyclonedds::domain::default_id());
dds::pub::Publisher publisher(participant);
dds::sub::Subscriber subscriber(participant);
dds::topic::Topic<HelloWorldData::Msg> topic(participant, "topic_name");
DomainParticipantListener participantListener;
SubscriberListener subscriberListener;
PublisherListener publisherListener;
dds::core::status::StatusMask participantMask = dds::core::status::StatusMask() << dds::core::status::StatusMask::data_on_readers();
dds::core::status::StatusMask publisherMask = dds::core::status::StatusMask() << dds::core::status::StatusMask::publication_matched();
dds::core::status::StatusMask subscriberMask = dds::core::status::StatusMask() << dds::core::status::StatusMask::subscription_matched();

participant.listener(&participantListener, participantMask);
publisher.listener(&publisherListener, publisherMask);
subscriber.listener(&subscriberListener, subscriberMask);

// Create reader and writer without listener
dds::pub::DataWriter<HelloWorldData::Msg> writer(publisher, topic);

dds::sub::DataReader<HelloWorldData::Msg> reader(subscriber, topic);

(or look at the unittest Listener.propagation)

This will cause an exception to be thrown in org::eclipse::cyclonedds::core::DDScObjectDelegate::extract_strong_ref as the function dds_create_writer in the DataWriter constructor has not completed yet, and therefore the entity id has not yet been able to have been added to the DDScObjectDelegate::entity_map lookup table. but the callback function has been triggered due to the listener being present on publisher.

use DDS_IGNORELOCAL_PROCESS with C++ API

I have a setup where I have a DDS reader and a DDS writer in the same process but would like to avoid that the DDS writer delivers to the local DDS reader.

In the C API I discovered the QoS DDS_IGNORELOCAL_PROCESS which is not supported by the C++ API. Nevertheless, I tried to apply it like the code below shows it but it does not seem to work

auto qos = ::dds::sub::qos::DataReaderQos();
auto* cqos = qos.delegate().ddsc_qos();
dds_qset_ignorelocal(cqos, DDS_IGNORELOCAL_PROCESS);
qos.delegate().ddsc_qos(cqos);

m_impl = ::dds::sub::DataReader<Mempool::Chunk>(subscriber, topic, qos);
free(cqos);

Did I use it wrongly or is the IGNORELOCAL_PROCESS QoS feature not at all supported with the C++ API? If so, is there a way to achieve the same behavior in C++?

API to get status of DDScObjectDelegate

Brief feature description

While using the Cyclone DDS CXX API, I realized that having an API like is_valid() (vendor-specific API) for DDScObjectDelegate will be helpful to check if the object is valid (checking if it is closed) before accessing the object.

Detailed information

With the current API, when I want to get a ddsc entity of an object then I need to do something like below:

ds::core::cond::StatusCondition & condition{};
auto foo = condition.delegate()->get_ddsc_entity();
...

The get_ddsc_entity() will internally check if the object is closed and throws an exception if it is closed, which is good in most scenarios, but in some use-cases, it is good (or required) to check if the object is valid before accessing anything from this object, something like below

ds::core::cond::StatusCondition & condition{};
if (condition.delegate()->is_valid() {
  auto foo = condition.delegate()->get_ddsc_entity();
  ...
}

From the code, it looks like it is easier to return this variable closed (of course guaranteeing the thread-safe behavior) to know the status of the delegate

I can add this API (assuming this is a sensible request), but I am not sure if I am missing anything here so pining @e-hndrks @k0ekk0ek @reicheratwork for thoughts.
Thanks in Advance.

Build problems - Windows VS2017

On Win 10 1909. Using Visual Studio 2017.

Have built cyclonedds and examples build and run ok. Now trying to cmake generate cyclonedds-cxx.

Following instructions on https://github.com/eclipse-cyclonedds/cyclonedds-cxx in "For application developers" in Windows.

$ cd build
$ cmake -G "<generator-name>" \
        -DCMAKE_INSTALL_PREFIX=<install-location> \
        -DCMAKE_PREFIX_PATH="<idlpp-cxx-install-location>;<cyclonedds-install-location>" \
        ..
$ cmake --build .

So I try to cmake generate with this command and get an error for idlcxx - maybe cmake can't find it:

D:\Code\VEMS\Prototyping\DDS_proto\cyclone_dds\third_party\cyclonedds-cxx\build>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX=D:\Code\VEMS\Prototyping\DDS_proto\cyclone_dds\third_party\cyclonedds-cxx\install -DCMAKE_PREFIX_PATH="C:\Program Files\Idlpp-cxx;D:\Code\VEMS\Prototyping\DDS_proto\cyclone_dds\third_party\cyclonedds\install" ..
-- Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.18363.
-- The C compiler identification is MSVC 19.16.27045.0
-- The CXX compiler identification is MSVC 19.16.27045.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Failed
-- Performing Test COMPILER_HAS_DEPRECATED
-- Performing Test COMPILER_HAS_DEPRECATED - Success
-- Configuring done
CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
  Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?


CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
  Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?


CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
  Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?


CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
  Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
  found.  Perhaps a find_package() call is missing for an IMPORTED target, or
  an ALIAS target is missing?


-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.

I'm not sure I've given the to idlcxx correctly. I used the installer from here: https://github.com/ADLINK-IST/idlpp-cxx/releases/tag/idlpp-cxx-1.0.0. CXX-Idl-compiler-for-Eclipse-CycloneDDS-1.0.0-win64-Windows_10_VS2019.msi

Help appreciated!

failed build cyclonedds-cxx-0.8.0beta1

got a error
cyclonedds-cxx-0.8.0beta1/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp:163:10: error: ‘dds_is_loan_available’ was not declared in this scope
return dds_is_loan_available(writer);
^~~~~~~~~~~~~~~~~~~~~
/home/xiaoran/work/cyclonedds-cxx-0.8.0beta1/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp:163:10: note: suggested alternative: ‘is_loan_available’
return dds_is_loan_available(writer);
^~~~~~~~~~~~~~~~~~~~~
is_loan_available

Alignment issue with C++ backend

Current Behaviour

With the current IDL compiler there is an issue with alignment when serializing the data. For a data struct like below:

struct PointField {
  string name = "foo"
  uint32 offset = 14
  uint8 datatype = 8
  uint32 count = 14
}

The serialized representation should look like below

   66 6f 6f 00   0e 00 00 00   08 00 00 00   0e 00 00 00   │ foo··········· │

However, it looks like the below, missing the alignment between offset and datatype fields. The serializer essentially ignored the alignment for byte-sized fields!

   66 6f 6f 00   0e 00 00 00   08 0e 00 00   00 00 00 00   │ foo············· │

Expected behavior

The alignment should always be correct

How to reproduce

Compile the following branches from cyclonedds and cycloneddds-cxx, then generate the code for the above IDL with idlc

Using LoanedSamples invokes deserialization multiple times

Current Behavior

When using the LoanedSamples as described below with the following version of Cyclone DDS

dds::sub::LoanedSamples<DDSType> dds_messages;
dds_messages = m_datareader.select().state(dds::sub::status::DataState::any()).max_samples(1).take();

if (dds_messages.length() > 0U) {
    const auto & it = dds_messages.begin();
    const auto & sample = it->data();
    const auto & sample_info = it->info();
...
# use sample and info
}

The same sample is deserialized twice.
As ddscxx_serdata stores the deserialized sample, calling getT() will anyways get the deserialized sample. However, the current code tries to deserialize the sample twice, once here in getT() which is called from serdata_from_ser() and second time here in serdata_from_ser().
I think this can be optimized to invoke read_struct() only once.

Expected Behaviour

The sample is deserialized only once in the take/read path with LoanedSamples.

Question: How can I redirect an error message?

I am wondering: How I can redirect an error message like this one 1621242890.222409 [0] 20352: can't open configuration file config_simple.xml. I would prefer a way to access the message in code. Is there an easy way to to this?

Serialization is incorrect with the updated streamer

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behaviour:

When an IDL type contains members with size > 1 byte, and when the value is 0 the serialization doesn't happen correctly

Detailed reproducer

When using the following IDL file

module msg
{
struct log {
boolean bool_values_[3];
octet byte_values_[3];
octet char_values_[3];
float float32_values_[3];
};
};

in the code as below:

TEST(tooch, serialize_deserialize)
{
  using DDSType = msg::log;

  // data
  DDSType msg{};
  msg.bool_values_(std::array<bool, 3>{false, true, false});
  msg.byte_values_(std::array<uint8_t, 3>{0, 255, 0});
  msg.char_values_(std::array<uint8_t, 3>{0, 255, 0});
  msg.float32_values_(std::array<float, 3>{0, 1.345, -12.34});

  org::eclipse::cyclonedds::core::cdr::basic_cdr_stream cdr_streamer;
  uint8_t buffer[1024];
  // fill the buffer to some non-zero to see the effect
  std::memset(buffer, 0xaa, sizeof(buffer));
  {
    //serialize
    cdr_streamer.set_buffer(buffer);
    org::eclipse::cyclonedds::core::cdr::write(cdr_streamer, msg);
    EXPECT_FALSE(cdr_streamer.abort_status());
  }
}

The serialized buffer looks as below:

00 01 00 00   ff 00 00 ff   00 00 00 00   00 aa aa aa   │ ················ │
 3f ac 28 f6   c1 45 70 a4 

The correct serialized buffer should look as below:

00 01 00 00   ff 00 00 ff   00 00 00 00   00 00 00 00   │ ················ │
 f6 28 ac 3f   a4 70 45 c1

I guess this is because of 2 reasons

  1. When an IDL member type has a size > 1 byte and has a value of 0 then only the first byte is changed to 0 and other bytes in the word are left as it is (unless the buffer is zero-initialized this will have some garbage)
    • I think this is also true during deserialization
  2. The logic for determining whether we need to swap the bytes because of endianness has a bug, this https://github.com/eclipse-cyclonedds/cyclonedds-cxx/blob/master/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/cdr_stream.hpp#L255 should actually check for inequality between local and stream endianness m_stream_endianness != m_local_endianness (and not for equality)

Expected result or behaviour:

The IDL types should be serialized/de-serialized correctly, regardless of the type and the value

Unions with identical types in different cases don't work

This:

union U switch(long)
{
  case 1:
    string aap;
  case 2:
    string noot;
};

causes (Apple) clang 12 in C++17 mode to error out with the following:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/variant:1440:59: error: no member named 'value' in 'std::__1::__find_exactly_one_t<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::basic_string<char>>'
  return _VSTD::get<__find_exactly_one_t<_Tp, _Types...>::value>(__v);
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
x.hpp:75:17: note: in instantiation of function template specialization 'std::__1::get<std::__1::basic_string<char>, std::__1::basic_string<char>, std::__1::basic_string<char>>' requested here
    return std::get<std::string>(m__u);

So it seems that the generated std::variant should not have duplicates. IDL allows it (and it is also perfectly sensible to allow this once there are typedefs and complex types).

issues while crosscompiling cyclonedds-cxx for latest master cyclonedds.

Issues while crosscompiling cyclonedds-cxx for latest master cyclonedds.

CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
found. Perhaps a find_package() call is missing for an IMPORTED target, or
an ALIAS target is missing?

CMake Error at src/idlcxx/CMakeLists.txt:14 (add_library):
Target "idlcxx" links to target "CycloneDDS::idl" but the target was not
found. Perhaps a find_package() call is missing for an IMPORTED target, or
an ALIAS target is missing?

cross-compile for aarch64 - cmake-toolchain-file
SET(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
SET(CMAKE_SYSTEM_VERSION 1)

set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Typedefs for arrays are always resolved

Array specifiers are always resolved because get_cpp11_type is used in the generator, even if it's a typedef. e.g.

typedef boolean barr[2];

struct foo {
  barr bar;
};

In this case the struct member uses std::array<boolean, 2>, while barr is expected. I've looked into it a bit, and while trivial, it does require quite a bit of code to be modified. I propose we fix it after the 0.8.0 release.

prevent_callbacks() function aborts during cleanup

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone Version

Observed result or behaviour:

In some very specific scenario's during cleanup, in function org::eclipse::cyclonedds::core::EntityDelegate::prevent_callbacks() the check assert(false) here fails causing the application to abort with out exiting cleanly.

Expected result or behaviour:

The usage of C++ API shouldn't lead to this abort in the runtime, or the API usage should be clearly specified with unhandled scenarios.

Conditions where it occurred / Performed steps:

As a workaround, during the cleanup I un-register the listener and then call close on the other DDS entities as shown below, which seems to not cause the error.

    // unregister the listener
    m_reader.listener(nullptr, dds::core::status::StatusMask::none());
    // close the guard condition
    m_guard_condition.close();
    // close the data reader
    m_reader->close();

Arrays in union cases not handled correctly

It completely ignores any array dimensions specified in a union case, e.g.:

union U switch(boolean) {
  case true: long a[2];
};
struct S {
  U u;
};
#pragma keylist S

results in:

class U
{
private:
  bool m__d;

  std::variant<int32_t> m__u;
...
  int32_t& a()
  {
    if (!_is_compatible_discriminator(m__d, true)) {
      throw dds::core::InvalidArgumentError(
        "Requested branch does not match current discriminator");
    }
    return std::get<int32_t>(m__u);
  }

  void a(int32_t u)
  {
    const bool d = true;
    if (!_is_compatible_discriminator(true, d)) {
      throw dds::core::InvalidArgumentError(
        "Discriminator does not match current discriminator");
    }
    m__d = d;
    m__u = u;
  }

sequence of bools in IDL doesn't work with libc++

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behaviour:

When a sequence of bools are used in the IDL, the templated streaming functions are not resolved correctly

Detailed reproducer

When using the following IDL file

module test_msgs {
module msg {
module dds_ {
struct BoundedSequences_ {
sequence<boolean, 3> bool_values_;
};
};  // module dds_
};  // module msg
};  // module test_msgs

in the code as below:

TEST(tooch, bound)
{
  using DDSType = test_msgs::msg::dds_::BoundedSequences_;
  dds::domain::DomainParticipant dp(0);
  dds::pub::Publisher pub(dp);
  dds::topic::Topic<DDSType> topic(dp, "test");
  dds::pub::DataWriter<DDSType> dw(pub, topic);
  DDSType msg{};
  std::vector<bool> vb{true, false, false, true};
  msg.bool_values_(vb);
  dw.write(msg);
}

Compile the code with Clang and it fails to resolve the templated streaming functions correctly with the following error

/home/sumanth.nirmal/tooch/new_idl/sequence_boolean.hpp:172:3: error: no matching function for call to 'move'
  move(streamer, instance.bool_values_()[i_1]);
  ^~~~
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/topic/datatopic.hpp:320:5: note: in instantiation of function template specialization 'org::eclipse::cyclonedds::core::cdr::move<org::eclipse::cyclonedds::core::cdr::basic_cdr_stream>' requested here
    move(str, msg);
    ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/topic/datatopic.hpp:510:4: note: in instantiation of function template specialization 'serdata_from_sample<test_msgs::msg::dds_::BoundedSequences_>' requested here
  &serdata_from_sample<T>,
   ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/topic/datatopic.hpp:538:25: note: in instantiation of static data member 'ddscxx_serdata<test_msgs::msg::dds_::BoundedSequences_>::ddscxx_serdata_ops' requested here
    &ddscxx_serdata<T>::ddscxx_serdata_ops,
                        ^
/home/sumanth.nirmal/tooch/new_idl/sequence_boolean.hpp:80:20: note: in instantiation of member function 'ddscxx_sertype<test_msgs::msg::dds_::BoundedSequences_>::ddscxx_sertype' requested here
    auto *st = new ddscxx_sertype<::test_msgs::msg::dds_::BoundedSequences_>();
                   ^
/home/sumanth.nirmal/tooch/new_idl/sequence_boolean.hpp:163:6: note: candidate function not viable: no known conversion from 'std::__1::vector<bool, std::__1::allocator<bool> >::const_reference' (aka '__bit_const_reference<std::__1::vector<bool, std::__1::allocator<bool> > >') to 'const ::test_msgs::msg::dds_::BoundedSequences_' for 2nd argument
void move(T& streamer, const ::test_msgs::msg::dds_::BoundedSequences_& instance)
     ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp:126:6: note: candidate template ignored: requirement 'std::is_arithmetic<__bit_const_reference<vector<bool, allocator<bool> > > >::value' was not satisfied [with T = std::__1::__bit_const_reference<std::__1::vector<bool, std::__1::allocator<bool> > >]
void move(basic_cdr_stream& str, const T& toincr)
     ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp:209:6: note: candidate template ignored: requirement 'std::is_enum<__bit_const_reference<vector<bool, allocator<bool> > > >::value' was not satisfied [with T = std::__1::__bit_const_reference<std::__1::vector<bool, std::__1::allocator<bool> > >]
void move(basic_cdr_stream& str, const T& toincr) {
     ^
/usr/include/c++/v1/type_traits:2290:1: note: candidate function template not viable: requires single argument '__t', but 2 arguments were provided
move(_Tp&& __t) _NOEXCEPT
^
/usr/include/c++/v1/iterator:1477:48: note: candidate function template not viable: requires 3 arguments, but 2 were provided
    template <class _Ip, class _Op> friend _Op move(_Ip, _Ip, _Op);
                                               ^
/usr/include/c++/v1/__bit_reference:691:1: note: candidate function template not viable: requires 3 arguments, but 2 were provided
move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result)
^
/usr/include/c++/v1/deque:725:1: note: candidate function template not viable: requires at least 3 arguments, but 2 were provided
move(_RAIter __f,
^
/usr/include/c++/v1/deque:755:1: note: candidate function template not viable: requires 3 arguments, but 2 were provided
move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
^
/usr/include/c++/v1/deque:783:1: note: candidate function template not viable: requires 3 arguments, but 2 were provided
move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
^
In file included from /home/sumanth.nirmal/gc/apex_ws/src/apex_os/core/apexutils/test/test_apexutils.cpp:430:
/home/sumanth.nirmal/tooch/new_idl/sequence_boolean.hpp:133:3: error: no matching function for call to 'write'
  write(streamer, instance.bool_values_()[i_1]);
  ^~~~~
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/topic/datatopic.hpp:339:5: note: in instantiation of function template specialization 'org::eclipse::cyclonedds::core::cdr::write<org::eclipse::cyclonedds::core::cdr::basic_cdr_stream>' requested here
    write(str, msg);
    ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/topic/datatopic.hpp:510:4: note: in instantiation of function template specialization 'serdata_from_sample<test_msgs::msg::dds_::BoundedSequences_>' requested here
  &serdata_from_sample<T>,
   ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/topic/datatopic.hpp:538:25: note: in instantiation of static data member 'ddscxx_serdata<test_msgs::msg::dds_::BoundedSequences_>::ddscxx_serdata_ops' requested here
    &ddscxx_serdata<T>::ddscxx_serdata_ops,
                        ^
/home/sumanth.nirmal/tooch/new_idl/sequence_boolean.hpp:80:20: note: in instantiation of member function 'ddscxx_sertype<test_msgs::msg::dds_::BoundedSequences_>::ddscxx_sertype' requested here
    auto *st = new ddscxx_sertype<::test_msgs::msg::dds_::BoundedSequences_>();
                   ^
/home/sumanth.nirmal/tooch/new_idl/sequence_boolean.hpp:124:6: note: candidate function not viable: no known conversion from 'std::__1::vector<bool, std::__1::allocator<bool> >::const_reference' (aka '__bit_const_reference<std::__1::vector<bool, std::__1::allocator<bool> > >') to 'const ::test_msgs::msg::dds_::BoundedSequences_' for 2nd argument
void write(T& streamer, const ::test_msgs::msg::dds_::BoundedSequences_& instance)
     ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp:100:6: note: candidate template ignored: requirement 'std::is_arithmetic<__bit_const_reference<vector<bool, allocator<bool> > > >::value' was not satisfied [with T = std::__1::__bit_const_reference<std::__1::vector<bool, std::__1::allocator<bool> > >]
void write(basic_cdr_stream& str, const T& towrite)
     ^
/home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp:197:6: note: candidate template ignored: requirement 'std::is_enum<__bit_const_reference<vector<bool, allocator<bool> > > >::value' was not satisfied [with T = std::__1::__bit_const_reference<std::__1::vector<bool, std::__1::allocator<bool> > >]
void write(basic_cdr_stream& str, const T& towrite) {
     ^

The reason for this is that the const reference of boolean vector is not defined as bool in libc++ though the standard seems to say so https://en.cppreference.com/w/cpp/container/vector_bool

Expected result or behaviour:

The sequence of bool type should also work with libc++

IDL: union with case TRUE fails to build

The following IDL snippet generates code but the code generated fails to build:

   union SomeType switch (boolean)
   {
     // the value when present
     case TRUE : long value;
   };

The compiler issues the following error:

/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldDataSplDcps.cpp: In function ‘void __HelloWorldData_SomeType__copyIn(const void*, void*)’:
/home/damian/projects/dependencies/cyclone-dds/cyclonedds-cxx/examples/helloworld/build/HelloWorldDataSplDcps.cpp:16:10: error: ‘TRUE’ was not declared in this scope
   16 |     case TRUE:
      |          ^~~~

The same IDL snippet generates compilerable code with OpenSplice.

Ubuntu 20.04, g++ 9.3.0

Problem in compilation in Cyclone-CXX IDL generated code

Hi Erik,
I am doing POC about communication between Cyclone and Opensplice DDS. Initially I am facing problem in compiling my Cyclone application code (IDL generated code gives some type conversion error at compilation).

My application code is on github (https://github.com/vivekpandey02/EclipseCycloneTest/)

my idl data types are below:

module TestCommand
{

/* ValueKind is the discriminator of the 'value' union of a KeyValue */
enum ValueKind {
    VALUEKIND_STRING,
    VALUEKIND_LONG,
    VALUEKIND_FLOAT,
    VALUEKIND_BOOLEAN
};

enum CommandKind {
    ADD_COMMAND,
    REMOVE_COMMAND
};

union Value switch(ValueKind) {
    case VALUEKIND_STRING:       /* Value is a string */
        string sValue;
    case VALUEKIND_LONG:         /* Value is a long number */
        long lValue;
    case VALUEKIND_FLOAT:        /* Value is a floating-point number */
        float fValue;
    case VALUEKIND_BOOLEAN:      /* Value is a boolean */
        boolean bValue;
};

/* Generic key:value type, where value is an union supporting various kinds of values */
struct KeyValue {
    string keyval;                   /* String key */
    Value value;
};

union Kind switch(CommandKind) {
    case ADD_COMMAND:                /* Add command */
        sequence<KeyValue> addCmd;
    case REMOVE_COMMAND:             /* Remove command */
        sequence<KeyValue> rmvCmd;  
};

struct TestCommandMsg
{
    long command_Id;
Kind kind;
};

#pragma keylist TestCommandMsg command_Id
};

idl compiler generated code successfully but when i build the application it gives errors:

vivekp@vivekp-Vostro-15-3568:~/cyclonedds-cxx/build/TestCommand$ cmake --build .Scanning dependencies of target isocpp_idlpp
[ 0%] Built target isocpp_idlpp
Scanning dependencies of target ddscxxTestCommand_lib_idl_isocpp_generate
[ 7%] Running isocpp_idlpp on TestCommand.idl
Compiling /home/vivekp/ADLINK/EcpliseCycloneDDS/share/CycloneDDS-CXX/examples/TestCommand/TestCommand.idl
ANTLR Tool version 4.4 used for code generation does not match the current runtime version 4.5ANTLR Tool version 4.4 used for code generation does not match the current runtime version 4.5[ 7%] Built target ddscxxTestCommand_lib_idl_isocpp_generate
Scanning dependencies of target ddscxxTestCommandPublisher
[ 15%] Building CXX object CMakeFiles/ddscxxTestCommandPublisher.dir/publisher.cpp.o
[ 23%] Building CXX object CMakeFiles/ddscxxTestCommandPublisher.dir/TestCommand.cpp.o
[ 30%] Building C object CMakeFiles/ddscxxTestCommandPublisher.dir/TestCommand-cyclone.c.o
[ 38%] Building CXX object CMakeFiles/ddscxxTestCommandPublisher.dir/TestCommandSplDcps.cpp.o
/home/vivekp/cyclonedds-cxx/build/TestCommand/TestCommandSplDcps.cpp: In function ‘void __TestCommand_Kind__copyIn(const void*, void*)’:
/home/vivekp/cyclonedds-cxx/build/TestCommand/TestCommandSplDcps.cpp:116:44: error: cannot convert ‘uint8_t* {aka unsigned char*}’ to ‘TestCommand_KeyValue*’ in assignment
to->_u.addCmd._buffer = (uint8_t )dest0;
^~~~~
/home/vivekp/cyclonedds-cxx/build/TestCommand/TestCommandSplDcps.cpp:138:44: error: cannot convert ‘uint8_t
{aka unsigned char*}’ to ‘TestCommand_KeyValue*’ in assignment
*to->_u.rmvCmd._buffer = (uint8_t )dest0;
^~~~~
CMakeFiles/ddscxxTestCommandPublisher.dir/build.make:156: recipe for target 'CMakeFiles/ddscxxTestCommandPublisher.dir/TestCommandSplDcps.cpp.o' failed
make[2]: *** [CMakeFiles/ddscxxTestCommandPublisher.dir/TestCommandSplDcps.cpp.o] Error 1
CMakeFiles/Makefile2:137: recipe for target 'CMakeFiles/ddscxxTestCommandPublisher.dir/all' failed
make[1]: *** [CMakeFiles/ddscxxTestCommandPublisher.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

'Share' folder not created

We found an issue while using cyclone-cxx for windows. It does not create share folder and copy examples to that folder which had to be manually.

Cheers
Phani

Deserialization of strings is incorrect

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behavior:

The deserialization doesn't happen correctly with the sequence/array of strings

Detailed reproducer

When using the following IDL file

module my_msg {
  module dds {
    typedef string string__3[3];
    struct msg {
      string__3 string_values;
    };
  };
};

in the code as below:

TEST(tooch, deserialize_string)
{
  using DDSType = my_msg::dds::msg;

  DDSType deserialized_msg{};

  // serialized buffer
  uint8_t serialized_buf[] =
  {0x01, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20,
    0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x31, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6d,
    0x70, 0x6c, 0x65, 0x78, 0x20, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x32, 0x00, 0x00, 0x0f, 0x00,
    0x00, 0x00, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
    0x33, 0x00, 0x00};

  //deserialize the buffer
  org::eclipse::cyclonedds::core::cdr::basic_cdr_stream cdr_streamer;
  cdr_streamer.set_buffer(serialized_buf + 4); // ignore the header
  org::eclipse::cyclonedds::core::cdr::read(cdr_streamer, deserialized_msg);
  EXPECT_FALSE(cdr_streamer.abort_status());
  EXPECT_STREQ(deserialized_msg.string_values()[0].c_str(), "Complex Hello1");
  EXPECT_STREQ(deserialized_msg.string_values()[1].c_str(), "Complex Hello2");
  EXPECT_STREQ(deserialized_msg.string_values()[2].c_str(), "Complex Hello3");
}

The test doesn't work (I have serialized the data by hand)
I guess this is because of 2 reasons

  1. The string_length - 1 here https://github.com/eclipse-cyclonedds/cyclonedds-cxx/blob/master/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp#L262 could lead to a huge number when the string is empty, which causes problems
  2. This alignment here https://github.com/eclipse-cyclonedds/cyclonedds-cxx/blob/master/src/ddscxx/include/org/eclipse/cyclonedds/core/cdr/basic_cdr_ser.hpp#L267 doesn't seem correct, it is not always aligned by 1, correct?

Expected result or behaviour:

The deserialization should work for all types in all scenarios

String header is not included in the generated code when custom container classes are used

Required information

Operating system:
Ubuntu 18.04 LTS

Branch:
templated_streaming, commit

Observed result or behaviour:
When a custom container is used for a string with the corresponding custom include file, the generated code doesn't include the header for the string container. This only happens when the type is a sequence of strings.

Reproducer
When the IDL file is used with the IDL compiler as below:

module test_msgs {
module msg {
module dds_ {

struct BoundedSequences_ {
 sequence<string<10>, 10> string_values;
};

};  // module dds_
};  // module msg
};  // module test_msgs
~/cyclone_iox_ws/cyclonedds/build/bin/idlc -l  ~/cyclone_iox_ws/cyclonedds-cxx/install/lib/libidlcxx.so -f bounded-string-template="ns::my_string<{BOUND}>" -f bounded-string-include="my_string.hpp" my_string.idl

The generated code looks as below, where it doesn't include the header for the string container

/****************************************************************

  Generated by Eclipse Cyclone DDS IDL to CXX Translator
  File name: my_string.idl
  Source: my_string.hpp
  Cyclone DDS: v0.8.0

*****************************************************************/
#ifndef DDSCXX_138197919_MY_STRING_HPP
#define DDSCXX_138197919_MY_STRING_HPP

#include <vector>

namespace test_msgs
{
namespace msg
{
namespace dds_
{
class BoundedSequences_
{
private:
 std::vector<ns::my_string<10>> string_values_;

public:
  BoundedSequences_() = default;

  explicit BoundedSequences_(
    const std::vector<ns::my_string<10>>& string_values) :
...

Expected result or behaviour:

The generated code should correctly include the header for the string container:

IDLC only partially implements struct inheritance

E.g.: the IDL4-to-C++11 language mapping says

[6.31.3]
The constructor which “accepts values for each struct member in the order they are specified in IDL” also accepts, as its first parameter, an object of the mapped base type (passed by const reference).

but the generated output has no such parameter — I haven't checked whether this is the only issue, but I suspect there are others as well.

See also eclipse-cyclonedds/cyclonedds#897

Streamer aborts with max bound for bounded strings

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behaviour:

When a bounded string with max bound is used the streamer aborts with an exception

Detailed reproducer

When using the following IDL file:

module msg
{
struct log {
string<255> text_;
};
};

The streamer aborts when the bounded string is used with the maximum bound as below:

TEST(tooch, bound)
{
  using DDSType = msg::log;
  dds::domain::DomainParticipant dp(0);
  dds::pub::Publisher pub(dp);
  dds::topic::Topic<DDSType> topic(dp, "test");
  dds::pub::DataWriter<DDSType> dw(pub, topic);
  DDSType msg{};
  msg.text_(
  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  dw.write(msg); // => Throws an exception
}

This throws an exception as below:

unknown file: Failure
C++ exception with description "Error Bad Parameter - write failed.
===============================================================================
Context     : void org::eclipse::cyclonedds::pub::AnyDataWriterDelegate::write
Node        : UnknownNode
" thrown in the test body.

Expected result or behaviour:

The streamer should gracefully handle the bounded strings with the maximum bound

helloworld example cmake issue - idlcxx branch

On Win 10 1909 using Visual Studio 2017.

Having trouble building the helloworld example in idlcxx branch.

Following instructions from: https://github.com/eclipse-cyclonedds/cyclonedds-cxx/tree/idlcxx#building-and-running-the-helloworld-example.

I get errors using cmake to configure the example. It seems like it can't find the cyclonedds-cxx cmake files. Sorry - I don't know enough about cmake to troubleshoot further.

D:\Code\VEMS\Prototyping\DDS_proto\cyclone_dds\helloworld-cxx>cmake D:\Code\VEMS\Prototyping\DDS_proto\cyclone_dds\third_party\cyclonedds-cxx\examples\helloworld
-- Building for: Visual Studio 15 2017
-- Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.18363.
-- The C compiler identification is MSVC 19.16.27045.0
-- The CXX compiler identification is MSVC 19.16.27045.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:16 (find_package):
  By not providing "FindCycloneDDS-CXX.cmake" in CMAKE_MODULE_PATH this
  project has asked CMake to find a package configuration file provided by
  "CycloneDDS-CXX", but CMake did not find one.

  Could not find a package configuration file provided by "CycloneDDS-CXX"
  with any of the following names:

    CycloneDDS-CXXConfig.cmake
    cyclonedds-cxx-config.cmake

  Add the installation prefix of "CycloneDDS-CXX" to CMAKE_PREFIX_PATH or set
  "CycloneDDS-CXX_DIR" to a directory containing one of the above files.  If
  "CycloneDDS-CXX" provides a separate development package or SDK, be sure it
  has been installed.


-- Configuring incomplete, errors occurred!
See also "D:/Code/VEMS/Prototyping/DDS_proto/cyclone_dds/helloworld-cxx/CMakeFiles/CMakeOutput.log".

Any assistance appreciated!

To-Do list for templated-streaming branch

  • 1. move cdr streaming implementations (basic_cdr_ser.hpp, cdr_stream.hpp, and any future expansions) away from topic directory to core directory
  • 2. move streaming functions into their own namespaces
    1. generated functions for structs and unions from parsed idl files
    2. implementations of cdr streaming endpoints (base types/strings)
  • 3. reject samples that produce invalid data, for instance reading a stream which exceeds the entries of a bounded sequence
    1. this can be handled by either return values from streaming functions, or exceptions thrown
    2. this also requires handling of the return values or exceptions in the ddscxx side
    3. make this behaviour configurable by user
  • 4. describe interface requirements of storage classes used in streaming functions
    1. since the new idl compiler allows for user-defined storage classes (sequence/string/union), the functions required to manipulate them should be enumerated
  • 5. correct parsing of keylists
    1. keylists at the moment just call the basic streaming functions on members which are keys, this is sufficient for basic types, but should be modified for keys which are structs, unions or typedefs
  • 6. add swap function for structs

DataReader<T>::take/read passing the wrong number of max samples

In TDataReaderImpl.hpp:
The unittests DataReaderSelector.read_FWIterator_instance and DataReaderSelector.take_FWIterator_instance show that the functions DataReader::take and DataReader::read pass the wrong number of max_samples to AnyDataReaderDelegate::take/read functions.
The max_samples parameter which is the maximum number of instances following the passed iterator SamplesFWIterator, is ignored. This is replaced by the max_samples_ member of selector.

The correct behaviour should be the smallest of max_samples and selector.max_samples_.

Take with loaned samples segfaults in SampleRef

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behavior:

In some specific scenarios take() with LoanedSample segfaults in SampleRef

Detailed reproducer

I am unsuccessful in creating a reproducer (maybe it is timing dependent), but the following are conditions when the segfault happens.

Below is the stack trace

#0  0x000055d7bfb7c1ca in ddsrt_atomic_dec32_ov (x=0xc) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds/install/include/dds/ddsrt/atomics/gcc.h:118
#1  0x000055d7bfb7c3c2 in ddsi_serdata_unref (serdata=0x0) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds/install/include/dds/ddsi/ddsi_serdata.h:245
#2  0x000055d7bfba9106 in dds::sub::detail::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_>::~SampleRef (this=0x55d7c0538f50, __in_chrg=<optimized out>) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/detail/SampleRef.hpp:64
#3  0x000055d7bfba73ca in dds::core::Value<dds::sub::detail::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_> >::~Value (this=0x55d7c0538f50, __in_chrg=<optimized out>) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/core/Value.hpp:128
#4  0x000055d7bfba73e6 in dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef>::~SampleRef (this=0x55d7c0538f50, __in_chrg=<optimized out>) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/TSampleRef.hpp:66
#5  0x000055d7bfba7401 in std::_Destroy<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef> > (__pointer=0x55d7c0538f50) at /usr/include/c++/7/bits/stl_construct.h:98
#6  0x000055d7bfba4abd in std::_Destroy_aux<false>::__destroy<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef>*> (__first=0x55d7c0538f50, __last=0x55d7c0538fb0) at /usr/include/c++/7/bits/stl_construct.h:108
#7  0x000055d7bfba202e in std::_Destroy<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef>*> (__first=0x55d7c0538f50, __last=0x55d7c0538fb0) at /usr/include/c++/7/bits/stl_construct.h:137
#8  0x000055d7bfb9e5d1 in std::_Destroy<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef>*, dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef> > (__first=0x55d7c0538f50, __last=0x55d7c0538fb0) at /usr/include/c++/7/bits/stl_construct.h:206
#9  0x000055d7bfbb437e in std::vector<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef>, std::allocator<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef> > >::_M_erase_at_end (this=0x55d7c0563630 = {...}, __pos=0x55d7c0538f50) at /usr/include/c++/7/bits/stl_vector.h:1518
#10 0x000055d7bfbb3885 in std::vector<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef>, std::allocator<dds::sub::SampleRef<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::SampleRef> > >::resize (this=0x55d7c0563630 = {...}, __new_size=0) at /usr/include/c++/7/bits/stl_vector.h:694
#11 0x000055d7bfbb2fa3 in dds::sub::detail::LoanedSamples<rcl_interfaces::msg::dds_::IntraProcessMessage_>::resize (this=0x55d7c0563630, s=0) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/detail/LoanedSamples.hpp:68
#12 0x000055d7bfbb0e33 in dds::sub::detail::LoanedSamplesHolder<rcl_interfaces::msg::dds_::IntraProcessMessage_>::set_length (this=0x7fffaa736050, len=0) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/detail/SamplesHolder.hpp:39
#13 0x00007f8c8955d074 in org::eclipse::cyclonedds::sub::AnyDataReaderDelegate::loaned_take (this=0x55d7c05627d0, reader=1716559570, mask=..., samples=..., requested_max_samples=1) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/sub/AnyDataReaderDelegate.cpp:376
#14 0x000055d7bfb9e40a in dds::sub::detail::DataReader<rcl_interfaces::msg::dds_::IntraProcessMessage_>::take (this=0x55d7c05627d0, selector=...) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/detail/TDataReaderImpl.hpp:1047
#15 0x000055d7bfb996ed in dds::sub::detail::DataReader<rcl_interfaces::msg::dds_::IntraProcessMessage_>::Selector::take (this=0x7fffaa736130) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/detail/TDataReaderImpl.hpp:908
#16 0x000055d7bfb92d38 in dds::sub::DataReader<rcl_interfaces::msg::dds_::IntraProcessMessage_, dds::sub::detail::DataReader>::Selector::take (this=0x7fffaa736130) at /home/sumanth.nirmal/cyclone_iox_ws/cyclonedds-cxx/install/include/ddscxx/dds/sub/detail/TDataReaderImpl.hpp:105
#17 0x000055d7bfb89024 in rosidl_typesupport_cyclone_dds_cpp::MessageSubscriber<apex::cyclone_dds::DDS_ROS_TypeTraits<rcl_interfaces::msg::IntraProcessMessage_<std::allocator<void> > > >::take (this=0x55d7c0560b30, count=1) at /home/sumanth.nirmal/gc/apex_ws/install/rosidl_typesupport_cyclone_dds_cpp/include/rosidl_typesupport_cyclone_dds_cpp/message_subscriber.hpp:179
#18 0x000055d7bfb809b2 in rclcpp::PollingSubscription<rcl_interfaces::msg::IntraProcessMessage_<std::allocator<void> >, std::allocator<void> >::take (this=0x55d7c0560dc0, count=1) at /home/sumanth.nirmal/gc/apex_ws/src/apex_os/core/rclcpp/rclcpp/include/rclcpp/polling_subscription.hpp:379
#19 0x000055d7bfb6fe98 in PollingSubscriptionTestBase_take_test_no_sample_Test::TestBody (this=0x55d7c053d0d0) at /home/sumanth.nirmal/gc/apex_ws/src/apex_os/core/rclcpp/rclcpp/test/test_polling_subscriber.cpp:374
#20 0x000055d7bfbe857e in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void> (object=0x55d7c053d0d0, method=&virtual testing::Test::TestBody(), location=0x55d7bfc024bb "the test body") at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2497
#21 0x000055d7bfbe1ea5 in testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> (object=0x55d7c053d0d0, method=&virtual testing::Test::TestBody(), location=0x55d7bfc024bb "the test body") at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2533
#22 0x000055d7bfbbf582 in testing::Test::Run (this=0x55d7c053d0d0) at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2572
#23 0x000055d7bfbbff17 in testing::TestInfo::Run (this=0x55d7c053a9a0) at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2753
#24 0x000055d7bfbc05c0 in testing::TestCase::Run (this=0x55d7c053a060) at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2875
#25 0x000055d7bfbcbbb2 in testing::internal::UnitTestImpl::RunAllTests (this=0x55d7c0539250) at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5318
#26 0x000055d7bfbe9777 in testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x55d7c0539250, method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x55d7bfbcb90c <testing::internal::UnitTestImpl::RunAllTests()>, location=0x55d7bfc02e48 "auxiliary test code (environments or event listeners)") at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2497
#27 0x000055d7bfbe2d49 in testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> (object=0x55d7c0539250, method=(bool (testing::internal::UnitTestImpl::*)(testing::internal::UnitTestImpl * const)) 0x55d7bfbcb90c <testing::internal::UnitTestImpl::RunAllTests()>, location=0x55d7bfc02e48 "auxiliary test code (environments or event listeners)") at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2533
#28 0x000055d7bfbca63e in testing::UnitTest::Run (this=0x55d7bfe52500 <testing::UnitTest::GetInstance()::instance>) at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:4926
#29 0x000055d7bfbb74ac in RUN_ALL_TESTS () at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2374
#30 0x000055d7bfbb743b in main (argc=1, argv=0x7fffaa736c08) at /home/sumanth.nirmal/gc/apex_ws/install/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:36
#31 0x00007f8c87ed6bf7 in __libc_start_main (main=0x55d7bfbb73fc <main(int, char**)>, argc=3, argv=0x7fffaa736c08, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffaa736bf8) at ../csu/libc-start.c:310
#32 0x000055d7bfb6973a in _start ()

Expected result or behaviour:

The take shouldn't segfault

Question concerning idl_ddscxx_generate

  • Can I call Idlcpp-cxx to generate source files and compile them into a library in a seperate cmake project using idl_ddscxx_generate?

Background: I basically want my project to be independent of the IDL cxx compiler. I want to have a seperate project where I only compile the IDL files. Then I want to copy the generated output (generate libraries and generated source files) to a seperate computer and use them there without having to install the IDL cxx compiler on that particular machine.

Missing headers in the generated code

Required information

Operating system:
Ubuntu 18.04 LTS

Cyclone version:

Observed result or behaviour:

The generated code doesn't include the required headers in the following scenarios (however, things might work because these get included with some other transient includes)

  1. The header <cstdint> is not included, which is required for the basic types like uint8_t, uint16_t etc.

  2. The header <array> is not included when the types are array
    For the following IDL file

    module test_msgs {
        module msg {
          module dds_ {
    
              struct Arrays_ {
                boolean bool_values_[3];
                octet byte_values_[3];
                octet char_values_[3];
              };
          };  // module dds_
        };  // module msg
    };  // module test_msgs

    The generated code doesn;t include the array header

    #ifndef DDSCXX_ARRAY_HPP
    #define DDSCXX_ARRAY_HPP
    
    namespace test_msgs
    {
    namespace msg
    {
    namespace dds_
    {
    class Arrays_
    {
    private:
      std::array<bool, 3> bool_values__ = { };
      std::array<uint8_t, 3> byte_values__ = { };
      std::array<uint8_t, 3> char_values__ = { };
    ...
  3. The string header is not included when the type is a string const
    For the IDL file below:

    module msg
    {
        module PrimitivesConstants_Constants {
      const string<3> STRING_CONST_ = "foo";
    };
    
    struct PrimitivesConstants_ {
      octet structure_needs_at_least_one_member_;
    };
    
    };  // module msg

    The generated code doesn't include the header for the string

    #ifndef DDSCXX_TOOCH_HPP
    #define DDSCXX_TOOCH_HPP
    
    namespace msg
    {
    namespace PrimitivesConstants_Constants
    {
    const std::string STRING_CONST_ = "foo";
    
    }
    
    class PrimitivesConstants_
    {
    private:
      uint8_t structure_needs_at_least_one_member__ = 0;
    1. This is also true when a custom container for the string is passed to the IDL compiler as follows -f bounded-string-template="MyString<{BOUND}>" -f bounded-string-include="<my_string.hpp>"
  4. The generated code has ddscxx_sertype, but there is no include nor a forward decleration for this in the generated code

  5. The generated code uses write/read.. from the basic_cdr_streamer, but doesn't include this basic_cdr_ser.hpp in the generated code.

Expected result or behaviour:
The generated code should correctly include the required headers in all scenarios

Issues with the updated IDL C++ generator

Required Information

Operating system:
Ubuntu 18.04 LTS

Compiler version:
GCC 7.5.0

Cyclone Version

Observed result or behavior

I have tried the updated IDL C++ generator and have encountered the following problems.

  1. The generated code for IDL containing an array of basic types, doesn't compile
    The problem I think is because the generated code has something like below, where its trying to convert an array to a basic type
      idl_array<bool, 10> bool_value__ = { };
      bool bool_value_() const { return this->bool_value__; }
    
    The compile error is as follows:
    error: cannot convert ‘const idl_array<bool, 10>’ to ‘bool’ in return
      bool bool_value_() const { return this->bool_value__; }
                                              ^~~~~~~~~~~~
    
    Updated: Then I realized this might be fixed with this MR #76 and it did fix this specific issue, but still have the following issues.
  2. Redeclaration of loop variable when IDL has an array, the generated code for read, write looks as below (where _a is redeclared)
    for (uint32_t _a = 0; _a < 10; _a++) {
    write(str, instance.bool_value_()[_a]);
    } //_a
    for (uint32_t _a = 0; _a < 10; _a++) {
    write(str, instance.byte_value_()[_a]);
    } //_a
    
  3. Redeclaration of a variable when IDL has a sequence, the generated code for read, write looks as below (where se_0 is redeclared)
    uint32_t se_0 = std::min<uint32_t>(uint32_t(instance.bool_value_().size()), 10);
    write(str, se_0);
    for (uint32_t i_0 = 0; i_0 < se_0; i_0++) {
    write(str, instance.bool_value_()[i_0]);
    } //i_0
    uint32_t se_0 = std::min<uint32_t>(uint32_t(instance.byte_value_().size()), 10);
    write(str, se_0);
    for (uint32_t i_0 = 0; i_0 < se_0; i_0++) {
    write(str, instance.byte_value_()[i_0]);
    } //i_0
    
  4. The nested IDL is included as <nested_idl_file_path>.h, but should be included as .hpp maybe here https://github.com/eclipse-cyclonedds/cyclonedds-cxx/blob/templated-streaming/src/idlcxx/src/generator.c#L638
  5. Ambiguous setter functions for strings (probably also true for other types) in the generated code, below shows the generated code
    void string_value_(const std::string _val_) { this->string_value__ = _val_; }
    void string_value_(std::string&& _val_) { this->string_value__ = _val_; }
    
    These 2 const and rvalue reference are pretty much the same, probably we should use const lvalue ref and rvalue ref for the setter functions.
  6. The generated code for the unbounded sequence of bools doesn't compile, below is the compilation error
    /home/sumanth.nirmal/cyclone_ws/cyclonedds-cxx/cmake-build-debug/examples/helloworld/HelloWorldData.hpp:170:7: error: no matching function for call to ‘read(basic_cdr_stream&, std::vector<bool>::reference)’
    read(str, instance.bool_value()[i_1]);
    ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
  7. Not everything required in TopicTraits.hpp is included,
    • std::vector is not included (though used here)
    • I am also not sure if <string.h> is required, if required then shouldn't this be included as <cstring>?
    • ddsi_sertype is not included (though used here. I am not sure if the assumption here is that these will be included with #include "dds/dds.hpp" from the application.
  8. Include directory option -I <directory> with the IDL compiler is not considered.
    Consider the following nested IDL nested_idl_setup.zip (where the included IDL is in a different path), and invoke the IDL compiler as below:
    // unzip the nested_idl_setup folder and run the following command from this folder
    ~/cyclone_ws/cyclonedds/build/bin/idlc -I /home/sumanth.nirmal/tooch/new_idl/nested_idl_setup/foo/bar/other/builtin_interfaces/ -l ~/cyclone_ws/cyclonedds-cxx/build/lib/libidlcxx.so -f case-sensitive Clock.idl 
    
    This gives the following error
    /home/sumanth.nirmal/tooch/new_idl/nested_idl_setup/Clock.idl:1: error: Can't open include file "builtin_interfaces/msg/Time.idl"
    #include "builtin_interfaces/msg/Time.idl"
    1 error in preprocessor.
    

Outstanding callback functions cause prevent_callbacks() in close() to fail an assert

Required information:

Operating system: Ubuntu 21.04
cyclonedds: master@32dee1fa90e87d57e26681ec2f5c86069e26b0be
cyclonedds-cxx: master@6ec026863a8a738d4980bfbfed13f35c55f3aed0

Description:
When a listener is attached to a dds::core::TEntity and the close() function is called on the object, while a callback function is executing from a different thread, when the ordering is "right", the close function can acquire the callback mutex, which then prevents the callback thread from "returning" the callback status, causing the function prevent_callbacks to fail an assert.

To Reproduce:
To illustrate this problem, I have attached a small demo program, which uses the same message types as in the helloworld examples:

/*
 * Copyright(c) 2021 ADLINK Technology Limited and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 * v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

#include <cstdlib>
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>

#include "dds/dds.hpp"
#include "dds/ddsrt/sync.h"
#include "dds/ddsrt/threads.h"

#include "HelloWorldData.hpp"

#define MAX_WRITERS 20

static ddsrt_mutex_t g_mutex;
static bool stop_writer_thread(false);
static std::vector< dds::pub::DataWriter<HelloWorldData::Msg> > writers;
  static const dds_duration_t delay(200000000);  // 200ms

static uint32_t writer_thread(void *arg)
{
    uintptr_t i = reinterpret_cast<uintptr_t>(arg);

    ddsrt_mutex_lock(&g_mutex);
    dds::pub::DataWriter<HelloWorldData::Msg> writer = writers[i];
    std::cout << "Created writer #: " << i << std::endl;
    ddsrt_mutex_unlock(&g_mutex);

    HelloWorldData::Msg testData(1, "test");

    while (!stop_writer_thread) {
        try {
            writer << testData;
        } catch (const dds::core::Exception& e) {
            std::cerr << "Writer [" << i << "] write fails: " << e.what() << std::endl;
            stop_writer_thread = true;
        } catch (...) {
            std::cerr << "Writer [" << i << "] write fails" << std::endl;
            stop_writer_thread = true;
        }
    }

    return 0;
}

class DummyListener : public virtual dds::sub::NoOpDataReaderListener<HelloWorldData::Msg>
{
public:
    DummyListener() { }

protected:
    virtual void on_data_available(dds::sub::DataReader<HelloWorldData::Msg>& ) { }
};

int main() {
  dds::domain::DomainParticipant dp(org::eclipse::cyclonedds::domain::default_id());
  dds::topic::Topic<HelloWorldData::Msg> topic(dp, "topic");
  dds::pub::Publisher pub(dp);
  dds::sub::Subscriber sub(dp);

  ddsrt_thread_t threadId[MAX_WRITERS];
  ddsrt_threadattr_t threadAttr;
  ddsrt_threadattr_init(&threadAttr);
  memset(threadId, 0, sizeof(threadId));
  ddsrt_mutex_init(&g_mutex);

  for (uintptr_t i = 0; i < MAX_WRITERS; i++) {
      ddsrt_mutex_lock(&g_mutex);
      writers.push_back(dds::pub::DataWriter<HelloWorldData::Msg>(pub, topic));
      (void)ddsrt_thread_create(
          &threadId[i], "writer_thread", &threadAttr, writer_thread, reinterpret_cast<void*>(i));
      ddsrt_mutex_unlock(&g_mutex);
  }
  dds_sleepfor(delay);

  dds::sub::DataReader<HelloWorldData::Msg> reader = dds::core::null;
  DummyListener readerListener;
  for (uint32_t i = 0; ; i++) {
    try {
      reader = dds::sub::DataReader<HelloWorldData::Msg>(sub, topic, sub.default_datareader_qos(),
        &readerListener, dds::core::status::StatusMask::data_available());
      if (reader != dds::core::null) {
        std::cout << "Created reader #: " << i << std::endl;
        dds_sleepfor(delay);
      } else {
        std::cerr << "reader = dds::core::null" << std::endl;
      }
    } catch (const dds::core::Exception& e) {
      std::cerr << "Exception: " << e.what() << std::endl;
    } catch (...) {
      std::cerr << "Unknown exception" << std::endl;
    }
    std::cout << "Destroying reader #: " << i << std::endl;
    reader = dds::core::null;
  }

  stop_writer_thread = true;
  for (uint32_t i = 0; i < MAX_WRITERS; i++) {
      (void)ddsrt_thread_join(threadId[i], NULL);
      ddsrt_mutex_lock(&g_mutex);
      writers[i] = dds::core::null;
      ddsrt_mutex_unlock(&g_mutex);
  }

  pub.close();
  sub.close();
  sub = dds::core::null;
  pub = dds::core::null;

  dp.close();
  dp = dds::core::null;

  ddsrt_mutex_destroy(&g_mutex);

  return EXIT_SUCCESS;
}

The following stack traces are created by this program:

This thread is attempting to finish executing a callback function on the DataReader at 0x5555555e3500 after a writer has delivered the data from a write call to the reader, it is waiting for the callback mutex to be released, however, this mutex is "stuck" inside the thread calling the destructor of the reading:

#0  __lll_lock_wait (futex=futex@entry=0x5555555e61b0, private=0) at lowlevellock.c:52
#1  0x00007ffff74a7903 in __GI___pthread_mutex_lock (mutex=0x5555555e61b0) at ../nptl/pthread_mutex_lock.c:80
#2  0x00007ffff7a74a45 in ddsrt_mutex_lock (mutex=0x5555555e61b0) at /mnt/hgfs/repos/cyclonedds/src/ddsrt/src/sync/posix/sync.c:44
#3  0x00007ffff7f24120 in org::eclipse::cyclonedds::core::EntityDelegate::release_callback_lock (this=0x5555555e3500) at /mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/core/EntityDelegate.cpp:284
#4  0x00007ffff7f271ac in callback_on_data_available (reader=2084321691, arg=0x5555555e3500) at /mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/core/ListenerDispatcher.cpp:181
#5  0x00007ffff7a39f8e in dds_reader_data_available_cb (rd=0x5555555e3ed0) at /mnt/hgfs/repos/cyclonedds/src/core/ddsc/src/dds_reader.c:201
#6  0x00007ffff7a428b3 in dds_rhc_default_store (rhc_common=0x5555555c43b0, wrinfo=0x7fffe17f9320, sample=0x7fffbc02caa0, tk=0x7fffac038400) at /mnt/hgfs/repos/cyclonedds/src/core/ddsc/src/dds_rhc_default.c:1752
#7  0x00007ffff79c3130 in ddsi_rhc_store (rhc=0x5555555c43b0, wrinfo=0x7fffe17f9320, sample=0x7fffbc02caa0, tk=0x7fffac038400) at /mnt/hgfs/repos/cyclonedds/src/security/api/../../core/ddsi/include/dds/ddsi/ddsi_rhc.h:66
#8  0x00007ffff79c5f60 in deliver_locally_fastpath (gv=0x5555555b2cc8, source_entity=0x5555555d8a70, source_entity_locked=false, fastpath_rdary=0x5555555d8cb0, wrinfo=0x7fffe17f9320, ops=0x7ffff7dbd140 <deliver_locally_ops>, 
    vsourceinfo=0x7fffe17f9300) at /mnt/hgfs/repos/cyclonedds/src/core/ddsi/src/ddsi_deliver_locally.c:231
#9  0x00007ffff79c60c4 in deliver_locally_allinsync (gv=0x5555555b2cc8, source_entity=0x5555555d8a70, source_entity_locked=false, fastpath_rdary=0x5555555d8cb0, wrinfo=0x7fffe17f9320, ops=0x7ffff7dbd140 <deliver_locally_ops>, 
    vsourceinfo=0x7fffe17f9300) at /mnt/hgfs/repos/cyclonedds/src/core/ddsi/src/ddsi_deliver_locally.c:257
#10 0x00007ffff7a57741 in deliver_locally (wr=0x5555555d8a70, payload=0x7fffbc02caa0, tk=0x7fffac038400) at /mnt/hgfs/repos/cyclonedds/src/core/ddsc/src/dds_write.c:267
#11 0x00007ffff7a57ad9 in dds_write_impl (wr=0x5555555d8400, data=0x7fffe17f95e0, tstamp=1624275262437617330, action=DDS_WR_ACTION_WRITE) at /mnt/hgfs/repos/cyclonedds/src/core/ddsc/src/dds_write.c:372
#12 0x00007ffff7a57160 in dds_write (writer=1465873778, data=0x7fffe17f95e0) at /mnt/hgfs/repos/cyclonedds/src/core/ddsc/src/dds_write.c:128
#13 0x00007ffff7f463d7 in org::eclipse::cyclonedds::pub::AnyDataWriterDelegate::write (this=0x5555555d8010, writer=1465873778, data=0x7fffe17f95e0, handle=..., timestamp=...)
    at /mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/pub/AnyDataWriterDelegate.cpp:175

This thread is attempting to execute the destructor of the DataReader at 0x5555555e3500. It has ownership of the mutex, which was acquired on entering prevent_callbacks, preventing the callback function thread from proceeding:

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
#1  0x00007ffff74e6864 in __GI_abort () at abort.c:79
#2  0x00007ffff74e6749 in __assert_fail_base (fmt=0x7ffff7672458 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x7ffff7f75ee1 "false", 
    file=0x7ffff7f75c58 "/mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/core/EntityDelegate.cpp", line=255, function=<optimized out>) at assert.c:92
#3  0x00007ffff74f8a96 in __GI___assert_fail (assertion=0x7ffff7f75ee1 "false", file=0x7ffff7f75c58 "/mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/core/EntityDelegate.cpp", line=255, 
    function=0x7ffff7f75e98 "void org::eclipse::cyclonedds::core::EntityDelegate::prevent_callbacks()") at assert.c:101
#4  0x00007ffff7f24017 in org::eclipse::cyclonedds::core::EntityDelegate::prevent_callbacks (this=0x5555555e3500) at /mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/src/org/eclipse/cyclonedds/core/EntityDelegate.cpp:255
#5  0x0000555555588484 in dds::sub::detail::DataReader<HelloWorldData::Msg>::close (this=0x5555555e3500) at /mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/include/dds/sub/detail/TDataReaderImpl.hpp:750
#6  0x0000555555587dfd in dds::sub::detail::DataReader<HelloWorldData::Msg>::~DataReader (this=0x5555555e3500, __in_chrg=<optimized out>, __vtt_parm=<optimized out>)
    at /mnt/hgfs/repos/cyclonedds-cxx/src/ddscxx/include/dds/sub/detail/TDataReaderImpl.hpp:518

As the callback function cannot finish the release_callback_lock function and decrement callback_count, the call to close will cause an assert failure.

IDL-Compiler: Constants cannot be used to declare a sequence

Hello everyone,
I have a problem with using a previously declared constant to create a sequence. To reproduce the problem, consider the following IDL file:

module Msg
{
    const long MAX_LENGTH = 10;
    const long MAX_NAMES = 5;

    struct StringSeq 
    {
        long id;
        sequence<string<MAX_LENGTH>, MAX_NAMES> names;
    };
    #pragma keylist StringSeq id
};

which should allow me to work with a vector with at most 5 strings of maximal 10 characters. Of course, the idea is to use those constants at several places in the IDL file. Now, I would like to write a message using cyclonedds-cxx. To this end, I just took the helloworld example, I changed the IDL file with mine above and replaced the content of the file publisher.cpp with:

#include <cstdlib>
#include <iostream>
#include <chrono>
#include <thread>
#include "dds/dds.hpp"
#include "StringSeq.hpp"
using namespace org::eclipse::cyclonedds;
int main() {
    dds::domain::DomainParticipant participant(0);
    dds::topic::Topic<Msg::StringSeq> topic(participant, "StringSeq");
    dds::pub::Publisher publisher(participant);
    dds::pub::DataWriter<Msg::StringSeq> writer(publisher, topic);
    while (writer.publication_matched_status().current_count() == 0) {
        std::this_thread::sleep_for(std::chrono::milliseconds(20));
    }
    std::vector<std::string> stringVector{"Signal1", "Signal2", "Signal3"};
    Msg::StringSeq msg(18, stringVector);
    writer.write(msg);
    while (writer.publication_matched_status().current_count() > 0) {
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
    return EXIT_SUCCESS;
}

Compiling the solution results in the error cannot evaluate <expression> as integer expression.
I have been using the commit 5ba9629 from the idlcxx branch.

Thank you in advance, any help would be appreciated.
Best regards,
Ettore Vidotto

CMAKE_BUILD_TYPE has no effect?

When I run
cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_INSTALL_PREFIX="D:/EclipseCylconeDDS/cyclonedds-cxx/install" -DCMAKE_PREFIX_PATH="D:/EclipseCylconeDDS/idlpp-cxx/install;D:/EclipseCylconeDDS/cyclonedds/install" -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=OFF .. && cmake --build . -j --target install

or
cmake -G "Visual Studio 15 2017" -DCMAKE_INSTALL_PREFIX="D:/EclipseCylconeDDS/cyclonedds-cxx/install_32" -DCMAKE_PREFIX_PATH="D:/EclipseCylconeDDS/idlpp-cxx/install;D:/EclipseCylconeDDS/cyclonedds/install_32" -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=OFF .. && cmake --build . -j --target install

I get the following warning

CMake Warning:
  Manually-specified variables were not used by the project:

    CMAKE_BUILD_TYPE

Apparently -DCMAKE_BUILD_TYPE=Release has no effect. What am I doing wrong here?

Extensions for shared memory support

Brief feature description

This issue lists and tracks the extensions required to support shared memory with cyclonedds-cxx.

Detailed information

The following should happen to fully support the shared memory through cyclonedds-cxx

  1. Type traits for the generated type to know if the type is fixed
  2. Set fixed size flag and sample size during the creation of ddsi_sertype
  3. Add C++ variants of iox specific serdata ops
    • ddsi_serdata_from_iox_t
    • ddsi_serdata_iox_size_t
  4. API to loan memory for writing a sample
  5. API to return loan on the write side
  6. API to return loan on the read side
  7. Add a helloworld example with SHM
  8. Test for scenario using SHM

Incorrect deserialization of unions with discriminants not mapping to a union case

This:

union a0005 switch (char) {
  case 'A':     a0006 a0009;
  case 'B':     double a0010;
};

generates a deserialization function:

template<typename T>
void read(T& streamer, ::a0005& instance)
{
  auto d = instance._d();
  read(streamer, d);
  switch(d)
  {
    case 'A':
  {
    ::a0006 obj;
  read__a0006(streamer, obj);
    instance.a0009(obj);
  }
  break;
    case 'B':
  {
    double obj = 0.0;
  read(streamer, obj);
    instance.a0010(obj);
  }
  break;
  }
  (void)streamer;
  (void)instance;
}

which means that it doesn't set the discriminant to the actual value read if it is neither 'A' nor 'B'. E.g., if the discriminant in the input is actually 'C', this will return a deserialized object with the discriminant set to 0 because of:

class a0005
{
private:
  char m__d;

  std::variant<::a0006, double> m__u;

  static const char _default_discriminator = 0x0;

  static char _is_discriminator(const char d)
  {
    switch (d) {
      case 'A':
        return 'A';
      case 'B':
        return 'B';
    }
    return _default_discriminator;
  }

idl-cxx: Segmentation fault while reading samples from datareader

Required information

Operating system:
E.g. Ubuntu 20.04 LTS

Compiler version:
E.g. GCC 9.3.0

Observed result or behaviour:
On iceoryx we want to update the CycloneDDS and CycloneDDS-CXX from the idl-pp generator to the new idlcxx generator on the idlcxx branch.
The work for this is done here: https://github.com/ApexAI/iceoryx/tree/iox-%23736-update-cyclonedds-to-idlcxx
Generation of the messages is successful and the header files are available.

We have in iceoryx a gateway written that split into two applications:

  1. iox-gw-iceoryx2dds has a iceoryx Subscriber and a DDS datawriter
  2. iox-gw-dds2iceoryx has a iceoryx Publisher and a DDS datareader

When running iox-gw-dds2iceoryx i get a segmentaion fault with the following message:

“./build/iceoryx_dds/iox-gw-dds2…” terminated by signal SIGSEGV (Address boundary error)

I was able to trace it to the point where the error occurs:
https://github.com/ApexAI/iceoryx/blob/c1d99922579ab079262b10faebd2ef36a38d2149/iceoryx_dds/source/iceoryx_dds/dds/cyclone_data_reader.cpp#L130

bool iox::dds::CycloneDataReader::hasSamples() noexcept
{
    auto samples = m_impl.select().max_samples(1u).state(::dds::sub::status::SampleState::any()).read();
    return samples.length() > 0;
}

The purpose of this function is to detect if there are samples available in the DDS reader, that is declared as follows:
https://github.com/ApexAI/iceoryx/blob/iox-%23736-update-cyclonedds-to-idlcxx/iceoryx_dds/include/iceoryx_dds/dds/cyclone_data_reader.hpp#L65

::dds::sub::DataReader<Mempool::Chunk> m_impl = ::dds::core::null;

I'm not sure if maybe the generated message is not correct or if we maybe misuse the DDS-CXX API here.
Is there maybe a more elegant way to determine if samples have arrived in the datareader?

Expected result or behaviour:
Segmentation fault does not occur.

Conditions where it occurred / Performed steps:

  1. Checkout the above mentioned branch
  2. Create in /etc/iceoryx/ a file called gateway_config.toml with the following code:
[[services]]
service = "Radar"
instance = "FrontLeft"
event = "Counter"
  1. Build iceoryx with the following command:
./tools/iceoryx_build_test.sh build-all debug clean
  1. Open a terminal in iceoryx folder and start roudi with
./build/iox-roudi
  1. Create another terminal in iceoryx folder and start the gateway application
./build/iceoryx_dds/iox-gw-dds2iceoryx

If you need more info like the generated message files, let me know.

Question about Cycloneddscxx

Hi, I'm relatively new to DDS and have some queries about the usage of cycloneddscxx.

  1. Is it possible to configure QoS XML with cycloneddscxx?

  2. If yes, is there any examples that I can take a reference to for configuring QoS with XML file?

Appreciate any assistance!

Best Regards,
Kyderio

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.