From 803883158b6df45ac5721bd1224ce1de5420cefa Mon Sep 17 00:00:00 2001 From: disganaitis Date: Fri, 6 Mar 2026 08:49:11 +0000 Subject: [PATCH 1/8] Initial version of the dds-xtypes rewrite in C for cyclonedds --- src/c/cyclone-dds-cmake/CMakeLists.txt | 12 + src/c/test_main.c | 1498 ++++++++++++++++++++++++ src/c/variant_eclipse_cyclone_dds.h | 182 +++ 3 files changed, 1692 insertions(+) create mode 100644 src/c/cyclone-dds-cmake/CMakeLists.txt create mode 100644 src/c/test_main.c create mode 100644 src/c/variant_eclipse_cyclone_dds.h diff --git a/src/c/cyclone-dds-cmake/CMakeLists.txt b/src/c/cyclone-dds-cmake/CMakeLists.txt new file mode 100644 index 0000000..1da40b6 --- /dev/null +++ b/src/c/cyclone-dds-cmake/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.16) +project(shape LANGUAGES C) + +# Find the CycloneDDS package. +find_package(CycloneDDS REQUIRED) +set(EXECUTABLE_NAME "eclipse_cyclone-${CycloneDDS_VERSION}_linux") + +add_executable(${EXECUTABLE_NAME} ../test_main.c) + +target_compile_definitions(${EXECUTABLE_NAME} PUBLIC -DCYCLONE_DDS) + +target_link_libraries(${EXECUTABLE_NAME} shape_lib CycloneDDS::ddsc m) diff --git a/src/c/test_main.c b/src/c/test_main.c new file mode 100644 index 0000000..9467065 --- /dev/null +++ b/src/c/test_main.c @@ -0,0 +1,1498 @@ +/**************************************************************** + * Use and redistribution is source and binary forms is permitted + * subject to the OMG-DDS INTEROPERABILITY TESTING LICENSE found + * at the following URL: + * + * https://github.com/omg-dds/dds-xtypes/blob/master/LICENSE.md + */ +/****************************************************************/ +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CYCLONEDDS + +#if defined(CYCLONEDDS) +#include "variant_eclipse_cyclone_dds.h" +#else +#error "Must define the DDS vendor" +#endif + +#define ERROR_PARSING_ARGUMENTS 1 +#define ERROR_INITIALIZING 2 +#define ERROR_RUNNING 3 + +/*************************************************************/ +int all_done = 0; +/*************************************************************/ +void handle_sig(int sig) +{ + if (sig == SIGINT) + { + all_done = 1; + } +} + +/*************************************************************/ +int install_sig_handlers() +{ + struct sigaction int_action; + int_action.sa_handler = handle_sig; + sigemptyset(&int_action.sa_mask); + sigaddset(&int_action.sa_mask, SIGINT); + int_action.sa_flags = 0; + sigaction(SIGINT, &int_action, NULL); + return 0; +} + +typedef enum Verbosity_e +{ + ERROR = 1, + DEBUG = 2, +} Verbosity; + +static char* to_string_reliability(dds_reliability_kind_t reliability_value) +{ + if (reliability_value == DDS_RELIABILITY_BEST_EFFORT) + { + return "BEST_EFFORT"; + } + else if (reliability_value == DDS_RELIABILITY_RELIABLE) + { + return "RELIABLE"; + } + return "Error stringifying Reliability kind."; +} + +static char* to_string_durability(dds_durability_kind_t durability_value) +{ + if (durability_value == DDS_DURABILITY_VOLATILE) + { + return "VOLATILE"; + } + else if (durability_value == DDS_DURABILITY_TRANSIENT_LOCAL) + { + return "TRANSIENT_LOCAL"; + } + else if (durability_value == DDS_DURABILITY_TRANSIENT) + { + return "TRANSIENT"; + } + else if (durability_value == DDS_DURABILITY_PERSISTENT) + { + return "PERSISTENT"; + } + return "Error stringifying Durability kind."; +} + +static char* to_string_data_representation(dds_data_representation_id_t data_representation_value) +{ + if (data_representation_value == DDS_DATA_REPRESENTATION_XCDR1) + { + return "XCDR"; + } + else if (data_representation_value == DDS_DATA_REPRESENTATION_XCDR2) + { + return "XCDR2"; + } + return "Error stringifying DataRepresentation."; +} + +static char* to_string_verbosity(Verbosity verbosity_value) +{ + switch (verbosity_value) + { + case ERROR: + return "ERROR"; + break; + + case DEBUG: + return "DEBUG"; + break; + + default: + break; + } + return "Error stringifying verbosity."; +} + +static char* to_string_ownership(dds_ownership_kind_t ownership_kind_value) +{ + if (ownership_kind_value == DDS_OWNERSHIP_SHARED) + { + return "SHARED"; + } + else if (ownership_kind_value == DDS_OWNERSHIP_EXCLUSIVE) + { + return "EXCLUSIVE"; + } + return "Error stringifying Ownership kind."; +} + +static char* to_string_history(dds_history_kind_t history_kind_value) +{ + if (history_kind_value == DDS_HISTORY_KEEP_ALL) + { + return "KEEP_ALL"; + } + else if (history_kind_value == DDS_HISTORY_KEEP_LAST) + { + return "KEEP_LAST"; + } + return "Error stringifying History kind."; +} + +static char* to_string_type_consistency(dds_type_consistency_kind_t consistency_kind_value) +{ + if (consistency_kind_value == DDS_TYPE_CONSISTENCY_DISALLOW_TYPE_COERCION) + { + return "DISALLOW_TYPE_COERCION"; + } + else if (consistency_kind_value == DDS_TYPE_CONSISTENCY_ALLOW_TYPE_COERCION) + { + return "ALLOW_TYPE_COERCION"; + } + return "Error stringifying TypeConsistency kind."; +} + +/*************************************************************/ +Verbosity verbosity = ERROR; + +void log_message(Verbosity level_verbosity, const char *format, ...) +{ + if (level_verbosity <= verbosity) + { + va_list arglist; + va_start(arglist, format); + vprintf(format, arglist); + va_end(arglist); + printf("\n"); + } +} + +/*************************************************************/ + +#define OPT_FORCE_TYPE_VALIDATION 0x1000 +#define OPT_CHECK_MEMBER_NAMES 0x1001 +#define OPT_CHECK_SEQUENCE_BOUNDS 0x1002 +#define OPT_CHECK_STRING_BOUNDS 0x1003 +#define OPT_PREVENT_TYPE_WIDENING 0x1004 +#define OPT_ALLOW_TYPE_COERCION 0x1005 +#define OPT_DISABLE_TYPE_INFO 0x1006 +#define OPT_TYPE_OBJECT_VERSION 0x1007 +#define OPT_PRINT_TYPEID 0x1008 + +static struct option long_opts[] = + { + {"help", no_argument, NULL, 'h'}, + {"force-type-validation", required_argument, NULL, OPT_FORCE_TYPE_VALIDATION}, + {"ignore-member-names", required_argument, NULL, OPT_CHECK_MEMBER_NAMES}, + {"ignore-seq-bounds", required_argument, NULL, OPT_CHECK_SEQUENCE_BOUNDS}, + {"ignore-str-bounds", required_argument, NULL, OPT_CHECK_STRING_BOUNDS}, + {"prevent-type-widening", required_argument, NULL, OPT_PREVENT_TYPE_WIDENING}, + {"allow-type-coercion", required_argument, NULL, OPT_ALLOW_TYPE_COERCION}, + {"disable-type-info", no_argument, NULL, OPT_DISABLE_TYPE_INFO}, + {"type-object-version", required_argument, NULL, OPT_TYPE_OBJECT_VERSION}, + {"print-typeid", no_argument, NULL, OPT_PRINT_TYPEID}, + {NULL, 0, NULL, 0}}; + +/*************************************************************/ +typedef struct TestOptions_s +{ + dds_domainid_t domain_id; + dds_reliability_kind_t reliability_kind; + dds_durability_kind_t durability_kind; + dds_data_representation_id_t data_representation; + int32_t history_depth; + int32_t ownership_strength; + + dds_type_consistency_kind_t type_consistency_kind; + bool ignore_sequence_bounds; + bool ignore_string_bounds; + bool ignore_member_names; + bool prevent_type_widening; + bool force_type_validation; + + char *topic_name; + char *type_name; + char *types_uri; /* xml file of defined types */ + + char *xml_data_uri; /* xml file of data sample */ + char *json_data_uri; /* json file of data sample */ + + char *partition; + + bool publish; + bool subscribe; + + int timebasedfilter_interval; + int deadline_interval; + + bool print_writer_samples; + + bool disable_type_info; + + int type_object_version; + bool print_typeid; +} TestOptions; + +//------------------------------------------------------------- +TestOptions TestOptions_create() +{ + TestOptions options; + + options.domain_id = 0; + options.reliability_kind = DDS_RELIABILITY_RELIABLE; + options.durability_kind = DDS_DURABILITY_VOLATILE; + options.data_representation = DDS_DATA_REPRESENTATION_XCDR1; + options.history_depth = -1; /* means default */ + options.ownership_strength = -1; /* means shared */ + + options.force_type_validation = DDS_BOOLEAN_FALSE; + options.ignore_member_names = DDS_BOOLEAN_TRUE; + options.ignore_sequence_bounds = DDS_BOOLEAN_TRUE; + options.ignore_string_bounds = DDS_BOOLEAN_TRUE; + options.prevent_type_widening = DDS_BOOLEAN_FALSE; + options.type_consistency_kind = DDS_TYPE_CONSISTENCY_ALLOW_TYPE_COERCION; +#if defined(RTI_CONNEXT_DDS) + type_consistency.ignore_enum_literal_names = + TypeConsistency_get_default().ignore_enum_literal_names; +#endif + + options.disable_type_info = false; + + options.topic_name = NULL; + options.type_name = NULL; + options.partition = NULL; + options.types_uri = NULL; + options.xml_data_uri = NULL; + options.json_data_uri = NULL; + + options.publish = false; + options.subscribe = false; + + options.timebasedfilter_interval = 0; /* off */ + options.deadline_interval = 0; /* off */ + + options.print_writer_samples = false; + + options.disable_type_info = false; + options.type_object_version = 2; + options.print_typeid = false; +} + +//------------------------------------------------------------- +void TestOptions_free(TestOptions *options) +{ + if (options->topic_name) + free(options->topic_name); + if (options->type_name) + free(options->type_name); + if (options->types_uri) + free(options->types_uri); + if (options->xml_data_uri) + free(options->xml_data_uri); + if (options->json_data_uri) + free(options->json_data_uri); + if (options->partition) + free(options->partition); +} + +//------------------------------------------------------------- +void print_usage(const char *prog) +{ + printf("%s: \n", prog); + printf(" -d : domain id (default: 0)\n"); + printf(" -b : BEST_EFFORT reliability\n"); + printf(" -r : RELIABLE reliability\n"); + printf(" -k : keep history depth [0: KEEP_ALL]\n"); + printf(" -f : set a 'deadline' with interval (seconds) [0: OFF]\n"); + printf(" -i : apply 'time based filter' with interval (seconds) [0: OFF]\n"); + printf(" -s : set ownership strength [-1: SHARED]\n"); + printf(" -t : set the topic name\n"); + printf(" -y : set the type name\n"); + printf(" -p : set a 'partition' string\n"); + printf(" -D [v|l|t|p] : set durability [v: VOLATILE, l: TRANSIENT_LOCAL]\n"); + printf(" t: TRANSIENT, p: PERSISTENT]\n"); + printf(" -P : publish samples\n"); + printf(" -S : subscribe samples\n"); + printf(" -x [1|2] : set data representation [1: XCDR, 2: XCDR2]\n"); + printf(" -X : xml file with type definitions\n"); + printf(" -V : xml file with data sample values. XML and JSON may be\n"); + printf(" provided, the app is in charge of using what it needs\n"); + printf(" -J : json file with data sample values. XML and JSON may be\n"); + printf(" provided, the app is in charge of using what it needs\n"); + printf(" -w : print Publisher's samples\n"); + printf(" --force-type-validation [t|f|d]: enable, disable or default value for\n"); + printf(" type_consistency.force_type_validation\n"); + printf(" --ignore-member-names [t|f|d]: enable, disable or default value for\n"); + printf(" type_consistency.ignore_member_names\n"); + printf(" --ignore-seq-bounds [t|f|d]: enable, disable or default value for\n"); + printf(" type_consistency.ignore_sequence_bounds\n"); + printf(" --ignore-str-bounds [t|f|d]: enable, disable or default value for\n"); + printf(" type_consistency.ignore_string_bounds\n"); + printf(" --prevent-type-widening [t|f|d]: enable, disable or default value for\n"); + printf(" type_consistency.prevent_type_widening\n"); + printf(" --allow-type-coercion [t|f|d]: enable, disable type coercion or default\n"); + printf(" value for type_consistency.kind\n"); + printf(" --disable-type-info: disable sending the type info for type\n"); + printf(" assignability\n"); + printf(" --type-object-version [1|2]: set the Type Object version to use.\n"); + printf(" Default: 2.\n"); + printf(" --print-typeid: print typeid (TypeObjectV1) or equivalence hash "); + printf(" (TypeObjectV2)\n"); + printf(" print_typeid\n"); + printf(" -v [e|d] : set log message verbosity [e: ERROR, d: DEBUG]\n"); +} + +//------------------------------------------------------------- +bool TestOptions_validate(TestOptions *options) +{ + if (options->topic_name == NULL) + { + log_message(ERROR, "topic name unspecified [-t], using \"test\" by default"); + return false; + } + if (options->type_name == NULL) + { + log_message(ERROR, "please specify type name [-y]"); + return false; + } + if ((!options->publish) && (!options->subscribe)) + { + log_message(ERROR, "please specify publish [-P] or subscribe [-S]"); + return false; + } + if (options->publish && options->subscribe) + { + log_message(ERROR, "please specify only one of: publish [-P] or subscribe [-S]"); + return false; + } +#if 0 /* allow publishing an empty, unpopulated sample */ + if ( options->xml_data_uri == NULL && options->json_data_uri == NULL ) { + log_message(ERROR, "please provide the data either in XML [-V] or JSON [-J]"); + return false; + } +#endif + if (options->types_uri == NULL) + { + log_message(ERROR, "please provide the types in XML [-X]"); + return false; + } + if ( options->type_consistency_kind != DDS_TYPE_CONSISTENCY_ALLOW_TYPE_COERCION + && options->ignore_sequence_bounds == DDS_BOOLEAN_TRUE + && options->ignore_string_bounds == DDS_BOOLEAN_TRUE + && options->ignore_member_names == DDS_BOOLEAN_TRUE + && options->prevent_type_widening == DDS_BOOLEAN_TRUE) + { + log_message(ERROR, + "warning: prevent_type_widening, ignore_sequence_bounds, ", + "ignore_string_bounds, and ignore_member_names only apply when the " + "type consistency kind is ALLOW_TYPE_COERCION" + ); + } + return true; +} + +//------------------------------------------------------------- +bool TestOptions_parse(TestOptions *options, int argc, char *argv[]) +{ + int opt; + bool parse_ok = true; + // double d; + while ((opt = getopt_long(argc, argv, + "hbrd:D:f:i:k:p:s:x:X:t:v:V:J:wy:PS", + long_opts, NULL)) != -1) + { + switch (opt) + { + case 'v': + { + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 'd': + { + verbosity = DEBUG; + break; + } + case 'e': + { + verbosity = ERROR; + break; + } + default: + { + log_message(ERROR, "unrecognized value for verbosity %c", optarg[0]); + parse_ok = false; + } + } + } + break; + } + case 'w': + { + options->print_writer_samples = true; + break; + } + case 'b': + { + options->reliability_kind = DDS_RELIABILITY_BEST_EFFORT; + break; + } + case 'd': + { + int converted_param = sscanf(optarg, "%d", &options->domain_id); + if (converted_param == 0) + { + log_message(ERROR, "unrecognized value for domain_id %c", optarg[0]); + parse_ok = false; + } + else if (options->domain_id < 0) + { + log_message(ERROR, "incorrect value for domain_id %u", options->domain_id); + parse_ok = false; + } + break; + } + case 'D': + { + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 'v': + { + options->durability_kind = DDS_DURABILITY_VOLATILE; + break; + } + case 'l': + { + options->durability_kind = DDS_DURABILITY_TRANSIENT_LOCAL; + break; + } + case 't': + { + options->durability_kind = DDS_DURABILITY_TRANSIENT; + break; + } + case 'p': + { + options->durability_kind = DDS_DURABILITY_PERSISTENT; + break; + } + default: + { + log_message(ERROR, "unrecognized value for durability %c", optarg[0]), + parse_ok = false; + } + } + } + break; + } + case 'i': + { + int converted_param = sscanf(optarg, "%d", &options->timebasedfilter_interval); + if (converted_param == 0) + { + log_message(ERROR, "unrecognized value for timebasedfilter_interval %c", optarg[0]); + parse_ok = false; + } + else if (options->timebasedfilter_interval < 0) + { + log_message(ERROR, "incorrect value for timebasedfilter_interval %d", options->timebasedfilter_interval); + parse_ok = false; + } + break; + } + case 'f': + { + int converted_param = sscanf(optarg, "%d", &options->deadline_interval); + if (converted_param == 0) + { + log_message(ERROR, "unrecognized value for deadline_interval %c", optarg[0]); + parse_ok = false; + } + else if (options->deadline_interval < 0) + { + log_message(ERROR, "incorrect value for deadline_interval %d", options->deadline_interval); + parse_ok = false; + } + break; + } + case 'k': + { + int converted_param = sscanf(optarg, "%d", &options->history_depth); + if (converted_param == 0) + { + log_message(ERROR, "unrecognized value for history_depth %c", optarg[0]); + parse_ok = false; + } + else if (options->history_depth < 0) + { + log_message(ERROR, "incorrect value for history_depth %d", options->history_depth); + parse_ok = false; + } + break; + } + case 'p': + { + options->partition = strdup(optarg); + break; + } + case 'r': + { + options->reliability_kind = DDS_RELIABILITY_RELIABLE; + break; + } + case 's': + { + int converted_param = sscanf(optarg, "%d", &options->ownership_strength); + if (converted_param == 0) + { + log_message(ERROR, "unrecognized value for ownership_strength %c", optarg[0]); + parse_ok = false; + } + else if (options->ownership_strength < -1) + { + log_message(ERROR, "incorrect value for ownership_strength ", options->ownership_strength); + parse_ok = false; + } + break; + } + case 't': + { + options->topic_name = strdup(optarg); + break; + } + case 'P': + { + options->publish = true; + break; + } + case 'S': + { + options->subscribe = true; + break; + } + case 'x': + { + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case '1': + { + options->data_representation = DDS_DATA_REPRESENTATION_XCDR1; + break; + } + case '2': + { + options->data_representation = DDS_DATA_REPRESENTATION_XCDR2; + break; + } + default: + { + log_message(ERROR, "unrecognized value for data representation %c", optarg[0]); + parse_ok = false; + } + } + } + break; + } + case 'X': + { + options->types_uri = strdup(optarg); + break; + } + case 'y': + { + options->type_name = strdup(optarg); + break; + } + case 'V': + { + options->xml_data_uri = strdup(optarg); + break; + } + case 'J': + { + options->json_data_uri = strdup(optarg); + break; + } + case OPT_FORCE_TYPE_VALIDATION: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 't': + options->force_type_validation = DDS_BOOLEAN_TRUE; + break; + case 'f': + options->force_type_validation = DDS_BOOLEAN_FALSE; + break; + case 'd': + options->force_type_validation = DDS_BOOLEAN_FALSE; + break; + default: + log_message(ERROR, "unrecognized value for type_consistency." + "force_type_validation %c", + optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_CHECK_MEMBER_NAMES: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 't': + options->ignore_member_names = DDS_BOOLEAN_TRUE; + break; + case 'f': + options->ignore_member_names = DDS_BOOLEAN_FALSE; + break; + case 'd': + options->ignore_member_names = DDS_BOOLEAN_FALSE; + break; + default: + log_message(ERROR, "unrecognized value for type_consistency." + "ignore_member_names %c", + optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_CHECK_SEQUENCE_BOUNDS: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 't': + options->ignore_sequence_bounds = DDS_BOOLEAN_TRUE; + break; + case 'f': + options->ignore_sequence_bounds = DDS_BOOLEAN_FALSE; + break; + case 'd': + options->ignore_sequence_bounds = DDS_BOOLEAN_FALSE; + break; + default: + log_message(ERROR, "unrecognized value for type_consistency." + "ignore_sequence_bounds %c", + optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_CHECK_STRING_BOUNDS: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 't': + options->ignore_string_bounds = DDS_BOOLEAN_TRUE; + break; + case 'f': + options->ignore_string_bounds = DDS_BOOLEAN_FALSE; + break; + case 'd': + options->ignore_string_bounds = DDS_BOOLEAN_FALSE; + break; + default: + log_message(ERROR, "unrecognized value for type_consistency." + "ignore_string_bounds %c", + optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_PREVENT_TYPE_WIDENING: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 't': + options->prevent_type_widening = DDS_BOOLEAN_TRUE; + break; + case 'f': + options->prevent_type_widening = DDS_BOOLEAN_FALSE; + break; + case 'd': + options->prevent_type_widening = DDS_BOOLEAN_FALSE; + break; + default: + log_message(ERROR, "unrecognized value for type_consistency." + "prevent_type_widening %c", + optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_ALLOW_TYPE_COERCION: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case 't': + options->type_consistency_kind = DDS_TYPE_CONSISTENCY_ALLOW_TYPE_COERCION; + break; + case 'f': + options->type_consistency_kind = DDS_TYPE_CONSISTENCY_DISALLOW_TYPE_COERCION; + break; + case 'd': + options->type_consistency_kind = DDS_TYPE_CONSISTENCY_ALLOW_TYPE_COERCION; + break; + default: + log_message(ERROR, "unrecognized value for type_consistency." + "kind %c", optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_DISABLE_TYPE_INFO: + options->disable_type_info = true; + break; + + case OPT_TYPE_OBJECT_VERSION: + if (optarg[0] != '\0') + { + switch (optarg[0]) + { + case '1': + options->type_object_version = 1; + break; + case '2': + options->type_object_version = 2; + break; + default: + log_message(ERROR, "unrecognized value for type object version %c", optarg[0]); + parse_ok = false; + break; + } + } + break; + + case OPT_PRINT_TYPEID: + options->print_typeid = true; + break; + + case 'h': + { + print_usage(argv[0]); + exit(0); + break; + } + case '?': + { + parse_ok = false; + break; + } + } + } + + if (parse_ok) + { + if (options->topic_name == NULL) + { + options->topic_name = strdup("test"); /* default.. */ + } + parse_ok = TestOptions_validate(options); + } + if (!parse_ok) + { + print_usage(argv[0]); + } + else + { + char* app_kind = options->publish ? "publisher" : "subscriber"; + log_message(DEBUG, "Test Options: "); + log_message(DEBUG, " This application is a %s", app_kind); + log_message(DEBUG, " DomainId = %u", options->domain_id); + log_message(DEBUG, " ReliabilityKind = %s", to_string_reliability(options->reliability_kind)); + log_message(DEBUG, " DurabilityKind = %s", to_string_durability(options->durability_kind)); + log_message(DEBUG, " DataRepresentation = %s", to_string_data_representation(options->data_representation)); + log_message(DEBUG, " HistoryDepth = %d", options->history_depth); + log_message(DEBUG, " OwnershipStrength = %d", options->ownership_strength); + log_message(DEBUG, " TimeBasedFilterInterval = %d", options->timebasedfilter_interval); + log_message(DEBUG, " DeadlineInterval = %d", options->deadline_interval); + log_message(DEBUG, " Type consistency kind = %s", to_string_type_consistency(options->type_consistency_kind)); + log_message(DEBUG, " Disable type info = %d", options->disable_type_info); + log_message(DEBUG, " TypeObject version = %d", options->type_object_version); + log_message(DEBUG, " Print Type ID = %d", options->print_typeid); + log_message(DEBUG, " Verbosity = %s", to_string_verbosity(verbosity)); + if (!options->publish) + { + log_message(DEBUG, " Force type validation = %d", options->force_type_validation); + log_message(DEBUG, " Ignore member names = %d", options->ignore_member_names); + log_message(DEBUG, " Ignore sequence bounds = %d", options->ignore_sequence_bounds); + log_message(DEBUG, " Ignore string bounds = %d", options->ignore_string_bounds); + log_message(DEBUG, " Prevent type widening = %d", options->prevent_type_widening); + } + + if (options->topic_name != NULL) + { + log_message(DEBUG, " Topic = %s", options->topic_name); + } + if (options->type_name != NULL) + { + log_message(DEBUG, " Type = %s", options->type_name); + } + if (options->types_uri != NULL) + { + log_message(DEBUG, " Types URI = %s", options->types_uri); + } + if (options->xml_data_uri != NULL) + { + log_message(DEBUG, " XML Data URI = %s", options->xml_data_uri); + } + if (options->json_data_uri != NULL) + { + log_message(DEBUG, " JSON Data URI = %s", options->json_data_uri); + } + if (options->partition != NULL) + { + log_message(DEBUG, " Partition = ", options->partition); + } + } + return parse_ok; +} + +char* helper_get_topic_name(dds_entity_t topic) +{ + char temp; + dds_return_t buf_len = dds_get_name(topic, &temp, 1) + 1; + char* topic_name = malloc(buf_len); + dds_get_name(topic, topic_name, buf_len); + return topic_name; +} +char* helper_get_type_name(dds_entity_t topic) +{ + char temp; + dds_return_t buf_len = dds_get_type_name(topic, &temp, 1) + 1; + char* type_name = malloc(buf_len); + dds_get_type_name(topic, type_name, buf_len); + return type_name; +} + +/*************************************************************/ +void on_inconsistent_topic(dds_entity_t topic, const dds_inconsistent_topic_status_t status, void* args) +{ + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s'\n", __FUNCTION__, topic_name, type_name); + free(topic_name); + free(type_name); +} + +void on_offered_incompatible_qos(dds_entity_t dw, const dds_offered_incompatible_qos_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dw); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + const char *policy_name = NULL; + policy_name = get_qos_policy_name(status.last_policy_id); + printf("%s() topic: '%s' type: '%s' : %d (%s)\n", __FUNCTION__, + topic_name, type_name, + status.last_policy_id, + policy_name); + free(topic_name); + free(type_name); +} + +void on_publication_matched(dds_entity_t dw, const dds_publication_matched_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dw); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s' : matched readers %d (change = %d)\n", __FUNCTION__, + topic_name, type_name, status.current_count, status.current_count_change); + free(topic_name); + free(type_name); +} + +void on_offered_deadline_missed(dds_entity_t dw, const dds_offered_deadline_missed_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dw); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s' : (total = %d, change = %d)\n", __FUNCTION__, + topic_name, type_name, status.total_count, status.total_count_change); + free(topic_name); + free(type_name); +} + +void on_liveliness_lost(dds_entity_t dw, const dds_liveliness_lost_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dw); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s' : (total = %d, change = %d)\n", __FUNCTION__, + topic_name, type_name, status.total_count, status.total_count_change); + free(topic_name); + free(type_name); +} + +void on_requested_incompatible_qos(dds_entity_t dr, const dds_requested_incompatible_qos_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dr); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + const char *policy_name = NULL; + policy_name = get_qos_policy_name(status.last_policy_id); + printf("%s() topic: '%s' type: '%s' : %d (%s)\n", __FUNCTION__, + topic_name, type_name, status.last_policy_id, + policy_name); + free(topic_name); + free(type_name); +} + +void on_subscription_matched(dds_entity_t dr, const dds_subscription_matched_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dr); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s' : matched writers %d (change = %d)\n", __FUNCTION__, + topic_name, type_name, status.current_count, status.current_count_change); + free(topic_name); + free(type_name); +} + +void on_requested_deadline_missed(dds_entity_t dr, const dds_requested_deadline_missed_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dr); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s' : (total = %d, change = %d)\n", __FUNCTION__, + topic_name, type_name, status.total_count, status.total_count_change); + free(topic_name); + free(type_name); +} + +void on_liveliness_changed(dds_entity_t dr, const dds_liveliness_changed_status_t status, void* args) +{ + dds_entity_t topic = dds_get_topic(dr); + char* topic_name = helper_get_topic_name(topic); + char* type_name = helper_get_type_name(topic); + printf("%s() topic: '%s' type: '%s' : (alive = %d, not_alive = %d)\n", __FUNCTION__, + topic_name, type_name, status.alive_count, status.not_alive_count); + free(topic_name); + free(type_name); +} + +void on_sample_rejected(dds_entity_t , const dds_sample_rejected_status_t status, void* args) {} +void on_data_available(dds_entity_t ) {} +void on_sample_lost(dds_entity_t , const dds_sample_lost_status_t status, void* args) {} +void on_data_on_readers(dds_entity_t ) {} + +/*************************************************************/ +typedef struct TestApplication_s +{ + dds_listener_t* dp_listener; + + dds_entity_t dp; + dds_entity_t pub; + dds_entity_t sub; + dds_entity_t topic; + dds_entity_t dr; + dds_entity_t dw; + dds_dynamic_type_t *dt; + dds_topic_descriptor_t* td; + +} TestApplication; + +bool TestApplication_init_publisher(TestApplication *app, TestOptions *options); +bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options); +bool TestApplication_run_publisher(TestApplication *app, TestOptions *options); +bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options); + +//------------------------------------------------------------- +TestApplication TestApplication_create() +{ + TestApplication app; + app.dp_listener = NULL; + app.dp = 0; + app.pub = 0; + app.sub = 0; + app.topic = 0; + app.dr = 0; + app.dw = 0; + app.dt = NULL; + + return app; +} + +//------------------------------------------------------------- +void TestApplication_free(TestApplication *app) +{ + if (app->dp_listener) + dds_delete_listener(app->dp_listener); + if (app->dt) + CLEANUP_TYPE(app->dp, app->dt); + if (app->dp) + dds_delete(app->dp); +} + +//------------------------------------------------------------- +bool TestApplication_initialize(TestApplication *app, TestOptions *options) +{ + dds_qos_t* dp_qos = dds_create_qos(); + + if (options->disable_type_info) + { + //disable_type_information(dp_qos); + } + + //set_type_object_version(dp_qos, options->type_object_version); + + app->dp = dds_create_participant(options->domain_id, dp_qos, NULL); + if (app->dp == 0) + { + log_message(ERROR, "failed to create participant (missing license?)."); + return false; + } + log_message(DEBUG, "Participant created"); + + app->dt = CREATE_TYPE(app->dp, options->types_uri, options->type_name); + if (app->dt == NULL) + { + log_message(ERROR, "failed to create type"); + return false; + } + + if (options->print_typeid) + { + PRINT_TYPEID(app->dt, options->type_object_version); + } + + if (REGISTER_TYPE(app->dp, app->dt, options->type_name) != DDS_RETCODE_OK) + { + log_message(ERROR, "failed to register type"); + return false; + } + + printf("Create topic: %s\n", options->topic_name); + app->topic = dds_create_topic(app->dp, app->dt); + if (app->topic == 0) + { + log_message(ERROR, "failed to create topic"); + return false; + } + + if (options->publish) + { + return TestApplication_init_publisher(app, options); + } + else + { + return TestApplication_init_subscriber(app, options); + } +} + +//------------------------------------------------------------- +bool TestApplication_run(TestApplication *app, TestOptions *options) +{ + if (app->pub != 0) + { + return TestApplication_run_publisher(app, options); + } + else if (app->sub != 0) + { + return TestApplication_run_subscriber(app, options); + } + CLEANUP_TYPE(app->dp, app->dt); + return false; +} + +//------------------------------------------------------------- +bool TestApplication_init_publisher(TestApplication *app, TestOptions *options) +{ + log_message(DEBUG, "Initializing Publisher"); + dds_return_t retcode; + dds_qos_t* pub_qos; + dds_qos_t* dw_qos; + + pub_qos = dds_create_qos(); + if (options->partition != NULL) + { + dds_qset_partition1(pub_qos, options->partition); + } + + app->pub = dds_create_publisher(app->dp, pub_qos, NULL); + if (app->pub == 0) + { + log_message(ERROR, "failed to create publisher"); + return false; + } + + log_message(DEBUG, "Publisher created"); + log_message(DEBUG, "Data Writer QoS:"); + + dw_qos = dds_create_qos(); + dds_qset_reliability(dw_qos, options->reliability_kind, 0); + { + dds_reliability_kind_t reliability; + dds_qget_reliability(dw_qos, &reliability, NULL); + log_message(DEBUG, " Reliability = %s", to_string_reliability(reliability)); + } + + dds_qset_durability(dw_qos, options->durability_kind); + { + dds_durability_kind_t durability; + dds_qget_durability(dw_qos, &durability); + log_message(DEBUG, " Durability = %s", to_string_durability(durability)); + } + + dds_qset_data_representation(dw_qos, 1, &options->data_representation); + { + dds_data_representation_id_t* data_representation; + uint32_t length; + dds_qget_data_representation(dw_qos, &length, &data_representation); + log_message(DEBUG, " Data_Representation = %s", to_string_data_representation(data_representation[0])); + } + + if (options->ownership_strength != -1) + { + dds_qset_ownership(dw_qos, DDS_OWNERSHIP_EXCLUSIVE); + dds_qset_ownership_strength(dw_qos, options->ownership_strength); + } + + if (options->ownership_strength == -1) + { + dds_qset_ownership(dw_qos, DDS_OWNERSHIP_SHARED); + } + { + dds_ownership_kind_t ownership; + dds_qget_ownership(dw_qos, &ownership); + log_message(DEBUG, " Ownership = %s", to_string_ownership(ownership)); + } + if (options->ownership_strength != -1) + { + int32_t ownership_strength; + dds_qget_ownership_strength(dw_qos, &ownership_strength); + log_message(DEBUG, " OwnershipStrength = %d", ownership_strength); + } + + if (options->deadline_interval > 0) + { + dds_qset_deadline(dw_qos, DDS_SECS(options->deadline_interval)); + } + { + dds_duration_t deadline; + dds_qget_deadline(dw_qos, &deadline); + log_message(DEBUG, " DeadlinePeriod = %d", deadline / DDS_SECS(1)); + } + + // options->history_depth < 0 means leave default value + if (options->history_depth > 0) + { + dds_qset_history(dw_qos, DDS_HISTORY_KEEP_LAST, options->history_depth); + } + else if (options->history_depth == 0) + { + dds_qset_history(dw_qos, DDS_HISTORY_KEEP_ALL, 0); + } + { + dds_history_kind_t history_kind; + int32_t history_depth; + dds_qget_history(dw_qos, &history_kind, &history_depth); + log_message(DEBUG, " History = %s", to_string_history(history_kind)); + if (history_kind == DDS_HISTORY_KEEP_LAST) + { + log_message(DEBUG, " HistoryDepth = %d", history_depth); + } + } + + printf("Create writer for topic: %s type: %s\n", options->topic_name, options->type_name); + + app->dw = dds_create_writer(app->pub, app->topic, dw_qos, NULL); + + if (app->dw == 0) + { + log_message(ERROR, "failed to create datawriter"); + return false; + } + + log_message(DEBUG, "Data Writer created"); + + return true; +} + +//------------------------------------------------------------- +bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options) +{ + dds_return_t retcode; + dds_qos_t* sub_qos; + dds_qos_t* dr_qos; + + sub_qos = dds_create_qos(); + if (options->partition != NULL) + { + dds_qset_partition1(sub_qos, options->partition); + } + + app->sub = dds_create_subscriber(app->dp, sub_qos, NULL); + if (app->sub == 0) + { + log_message(ERROR, "failed to create subscriber"); + return false; + } + + log_message(DEBUG, "Subscriber created"); + log_message(DEBUG, "Data Reader QoS:"); + + dr_qos = dds_create_qos(); + + dds_qset_reliability(dr_qos, options->reliability_kind, 0); + { + dds_reliability_kind_t reliability; + dds_qget_reliability(dr_qos, &reliability, NULL); + log_message(DEBUG, " Reliability = ", to_string_reliability(reliability)); + } + + dds_qset_durability(dr_qos, options->durability_kind); + { + dds_durability_kind_t durability; + dds_qget_durability(dr_qos, &durability); + log_message(DEBUG, " Durability = %s", to_string_durability(durability)); + } + + dds_qset_data_representation(dr_qos, 1, &options->data_representation); + { + dds_data_representation_id_t* data_representation; + uint32_t length; + dds_qget_data_representation(dr_qos, &length, &data_representation); + log_message(DEBUG, " Data_Representation = %s", to_string_data_representation(data_representation[0])); + } + + if (options->ownership_strength != -1) + { + dds_qset_ownership(dr_qos, DDS_OWNERSHIP_EXCLUSIVE); + dds_qset_ownership_strength(dr_qos, options->ownership_strength); + } + { + dds_ownership_kind_t ownership; + dds_qget_ownership(dr_qos, &ownership); + log_message(DEBUG, " Ownership = %s", to_string_ownership(ownership)); + } + + if (options->timebasedfilter_interval > 0) + { + dds_qset_time_based_filter(dr_qos, DDS_SECS(options->timebasedfilter_interval)); + } + { + dds_duration_t time_based_filter; + dds_qget_time_based_filter(dr_qos, &time_based_filter); + log_message(DEBUG, " TimeBasedFilter = %d", time_based_filter / DDS_SECS(1)); + } + + if (options->deadline_interval > 0) + { + dds_qset_deadline(dr_qos, DDS_SECS(options->deadline_interval)); + } + { + dds_duration_t deadline; + dds_qget_deadline(dr_qos, &deadline); + log_message(DEBUG, " DeadlinePeriod = %d", deadline / DDS_SECS(1)); + } + + // options->history_depth < 0 means leave default value + if (options->history_depth > 0) + { + dds_qset_history(dr_qos, DDS_HISTORY_KEEP_LAST, options->history_depth); + } + else if (options->history_depth == 0) + { + dds_qset_history(dr_qos, DDS_HISTORY_KEEP_ALL, 0); + } + { + dds_history_kind_t history_kind; + int32_t history_depth; + dds_qget_history(dr_qos, &history_kind, &history_depth); + log_message(DEBUG, " History = %s", to_string_history(history_kind)); + if (history_kind == DDS_HISTORY_KEEP_LAST) + { + log_message(DEBUG, " HistoryDepth = %d", history_depth); + } + } + + dds_qset_type_consistency( + dr_qos, + options->type_consistency_kind, + options->ignore_sequence_bounds, + options->ignore_string_bounds, + options->ignore_member_names, + options->prevent_type_widening, + options->force_type_validation); + { + dds_type_consistency_kind_t type_consistency_kind; + bool ignore_sequence_bounds; + bool ignore_string_bounds; + bool ignore_member_names; + bool prevent_type_widening; + bool force_type_validation; + + dds_qget_type_consistency( + dr_qos, + &type_consistency_kind, + &ignore_sequence_bounds, + &ignore_string_bounds, + &ignore_member_names, + &prevent_type_widening, + &force_type_validation); + log_message(DEBUG, " TypeConsistency * kind = %s", to_string_type_consistency(type_consistency_kind)); + log_message(DEBUG, " * ignore_sequence_bounds = %d", ignore_sequence_bounds); + log_message(DEBUG, " * ignore_string_bounds = %d", ignore_string_bounds); + log_message(DEBUG, " * ignore_member_names = %d", ignore_member_names); + log_message(DEBUG, " * prevent_type_widening = %d", prevent_type_widening); + log_message(DEBUG, " * force_type_validation = %d", force_type_validation); + } + + printf("Create reader for topic: %s\n", options->topic_name); + + app->dr = dds_create_reader(app->sub, app->topic, dr_qos, NULL); + if (app->dr == 0) + { + log_message(ERROR, "failed to create datareader"); + return false; + } + + log_message(DEBUG, "Data Reader created"); + return true; +} + +//------------------------------------------------------------- +bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) +{ + while (!all_done) + { + dds_return_t retval; + void* samples = malloc(sizeof(int*) * 10000); + for(int i = 0; i < 10000; i++) + { + ((void**)samples)[i] = NULL; + } + dds_sample_info_t* sample_infos = malloc(sizeof(dds_sample_info_t) * 10000); + + do + { + retval = dds_take(app->dr, + &samples, + sample_infos, + sizeof(int *) * 10000, + 10000); + if (retval >= 0) + { + unsigned int i; + for (i = 0; i < retval; i++) + { + DynamicData *sample = &samples[i]; + dds_sample_info_t *sample_info = &sample_infos[i]; + + if (sample_info->valid_data) + { + printf("sample_received()\n"); + PRINT_DATA(sample); + if (CHECK_DATA(sample, options->xml_data_uri, options->json_data_uri)) + { + printf("Received sample is the same as loaded\n"); + } + else + { + printf("Received sample is not the same as loaded\n"); + } + } + } + + } + dds_return_loan(app->dr, &samples, 10000 * sizeof(int*)); + } while (retval >= 0); + + dds_sleepfor(DDS_USECS(100000)); + } + + return true; +} + +//------------------------------------------------------------- +bool TestApplication_run_publisher(TestApplication *app, TestOptions *options) +{ + DDS::DynamicData *dd = CREATE_DATA(dt); + if (dd == NULL) + { + log_message(ERROR, "Error creating DynamicData"); + return false; + } + + if (INIT_DATA(dd, options->xml_data_uri, options->json_data_uri) != DDS_RETCODE_OK) + { + log_message(ERROR, "Error initializing data"); + return false; + } + + while (!all_done) + { + DynamicDataWriter *ddw = dynamic_cast(dw); + ddw->write(*dd, HANDLE_NIL); + if (options->print_writer_samples) + { + printf(" Wrote:\n"); + PRINT_DATA(dd); + } + dds_sleepfor(DDS_USECS(1000000)); + } + CLEANUP_DATA(dd); + return true; +} + +/*************************************************************/ +int main(int argc, char *argv[]) +{ + install_sig_handlers(); + + TestOptions options; + TestOptions_create(&options); + bool parseResult = TestOptions_parse(&options, argc, argv); + if (!parseResult) + { + exit(ERROR_PARSING_ARGUMENTS); + } + TestApplication testApp; + TestApplication_create(&testApp); + if (!TestApplication_initialize(&testApp, &options)) + { + exit(ERROR_INITIALIZING); + } + if (!TestApplication_run(&testApp, &options)) + { + exit(ERROR_RUNNING); + } + + printf("Done.\n"); + + return 0; +} diff --git a/src/c/variant_eclipse_cyclone_dds.h b/src/c/variant_eclipse_cyclone_dds.h new file mode 100644 index 0000000..3c1af7c --- /dev/null +++ b/src/c/variant_eclipse_cyclone_dds.h @@ -0,0 +1,182 @@ +#include "dds/dds.h" + +#define DDS_BOOLEAN_TRUE (1) +#define DDS_BOOLEAN_FALSE (0) +#define LISTENER_STATUS_MASK_ALL (ALL_STATUS) + +const char* get_qos_policy_name(uint32_t last_policy_id) { + + switch (last_policy_id) { + case DDS_INVALID_QOS_POLICY_ID: return "INVALID"; + case DDS_USERDATA_QOS_POLICY_ID: return "USERDATA"; + case DDS_DURABILITY_QOS_POLICY_ID: return "DURABILITY"; + case DDS_PRESENTATION_QOS_POLICY_ID: return "PRESENTATION"; + case DDS_DEADLINE_QOS_POLICY_ID: return "DEADLINE"; + case DDS_LATENCYBUDGET_QOS_POLICY_ID: return "LATENCYBUDGET"; + case DDS_OWNERSHIP_QOS_POLICY_ID: return "OWNERSHIP"; + case DDS_OWNERSHIPSTRENGTH_QOS_POLICY_ID: return "OWNERSHIPSTRENGTH"; + case DDS_LIVELINESS_QOS_POLICY_ID: return "LIVELINESS"; + case DDS_TIMEBASEDFILTER_QOS_POLICY_ID: return "TIMEBASEDFILTER"; + case DDS_PARTITION_QOS_POLICY_ID: return "PARTITION"; + case DDS_RELIABILITY_QOS_POLICY_ID: return "RELIABILITY"; + case DDS_DESTINATIONORDER_QOS_POLICY_ID: return "DESTINATIONORDER"; + case DDS_HISTORY_QOS_POLICY_ID: return "HISTORY"; + case DDS_RESOURCELIMITS_QOS_POLICY_ID: return "RESOURCELIMITS"; + case DDS_ENTITYFACTORY_QOS_POLICY_ID: return "ENTITYFACTORY"; + case DDS_WRITERDATALIFECYCLE_QOS_POLICY_ID: return "WRITERDATALIFECYCLE"; + case DDS_READERDATALIFECYCLE_QOS_POLICY_ID: return "READERDATALIFECYCLE"; + case DDS_TOPICDATA_QOS_POLICY_ID: return "TOPICDATA"; + case DDS_GROUPDATA_QOS_POLICY_ID: return "GROUPDATA"; + case DDS_TRANSPORTPRIORITY_QOS_POLICY_ID: return "TRANSPORTPRIORITY"; + case DDS_LIFESPAN_QOS_POLICY_ID: return "LIFESPAN"; + case DDS_DURABILITYSERVICE_QOS_POLICY_ID: return "DURABILITYSERVICE"; + case DDS_PROPERTY_QOS_POLICY_ID: return "PROPERTY"; + case DDS_TYPE_CONSISTENCY_ENFORCEMENT_QOS_POLICY_ID: return "TYPE_CONSISTENCY_ENFORCEMENT"; + case DDS_DATA_REPRESENTATION_QOS_POLICY_ID: return "DATAREPRESENTATION"; + default: + return 0; + } +} + +dds_dynamic_type_t * +CREATE_TYPE( dds_entity_t dp, + const char * types_uri, + const char * type_name ) +{ + dds_dynamic_type_t* dt = NULL; + if ( dp && types_uri && type_name ) + { + DDS::DynamicTypeBuilderFactory * dtbf = + DDS::DynamicTypeBuilderFactoryXml::get_instance( ); + if ( dtbf ) + { + DDS::DynamicTypeBuilder * dtb = + dtbf->create_type_w_uri ( types_uri, + type_name, + NULL ); + if ( dtb ) + { + dt = dtb->build( ); + dtbf->delete_type_builder( dtb ); + } + } + } + return dt; +} + +dds_return_t +REGISTER_TYPE( dds_entity_t dp, + dds_dynamic_type_t* dt, + const char* type_name ) +{ + dds_return_t retval = DDS_RETCODE_ERROR; + if ( dp && dt && type_name ) + { + DDS::DynamicTypeSupport * dts = + DDS::DynamicTypeSupport::create_type_support ( dt ); + if ( dts ) + { + retval = dts->register_type( dp, type_name ); + } + } + return retval; +} + +void +CLEANUP_TYPE( dds_entity_t dp, + dds_dynamic_type_t* dt ) +{ + if ( dp && dt ) + { + DDS::DynamicTypeBuilderFactory * dtbf = + DDS::DynamicTypeBuilderFactoryXml::get_instance( ); + dtbf->delete_type( dt ); + } +} + +DDS::DynamicData * +CREATE_DATA( DDS::DynamicType * dt ) +{ + DDS::DynamicData * retval = NULL; + DDS::DynamicDataFactory * ddf = DDS::DynamicDataFactory::get_instance(); + if ( ddf ) + { + retval = ddf->create_data( dt ); + } + return retval; +} + +DDS::ReturnCode_t +INIT_DATA( DDS::DynamicData * dd, + const char * xml_data_uri, + const char * json_data_uri ) +{ + DDS::ReturnCode_t retval = DDS::RETCODE_ERROR; + if ( dd ) + { + fflush( stderr ); + if ( xml_data_uri ) + { + retval = coredx::DynamicData_init_from_xmluri( dd, xml_data_uri ); + } + else + { + /* no specific data, just init to 'defaults' */ + fprintf( stderr, "[ No data to load. Using empty sample... ]\n" ); + fflush( stderr ); + retval = DDS::RETCODE_OK; + } + } + return retval; +} + +void +PRINT_DATA( DDS::DynamicData * dd ) +{ + // coredx::DynamicData_print( stderr, dd, 0 ); + coredx::DynamicData_print_xml( stdout, dd, 0 ); +} + +void CLEANUP_DATA(DDS::DynamicData *dd) +{ + DDS::DynamicDataFactory * ddf = DDS::DynamicDataFactory::get_instance(); + ddf->delete_data( dd ); +} + + +bool +CHECK_DATA(DDS::DynamicData *dd, + const char *xml_data_uri, + const char *json_data_uri) +{ + bool retval = false; + + if (dd == NULL && json_data_uri == NULL) { + return retval; + } + + DDS::DynamicData *data_check = + CREATE_DATA( (DDS::DynamicType *) dd->get_type() ); + + if (data_check == NULL) { + retval = false; + goto done; + } + if (INIT_DATA(data_check, xml_data_uri, json_data_uri) != DDS_RETCODE_OK) { + retval = false; + goto done; + } + + retval = dd->equals(data_check); + if ( !retval ) + { + printf("Expected:\n"); + PRINT_DATA( data_check ); + } + + done: + if (data_check != NULL) { + CLEANUP_DATA(data_check); + } + return retval; +} From ffe980196c6731a02943874e8ee42801db8f2561 Mon Sep 17 00:00:00 2001 From: disganaitis Date: Tue, 10 Mar 2026 12:37:12 +0000 Subject: [PATCH 2/8] Added api calls to Eriks custom dynamic type xml branch --- src/c/test_main.c | 51 ++++++----- src/c/variant_eclipse_cyclone_dds.h | 126 +++++++--------------------- 2 files changed, 57 insertions(+), 120 deletions(-) diff --git a/src/c/test_main.c b/src/c/test_main.c index 9467065..6a9de34 100644 --- a/src/c/test_main.c +++ b/src/c/test_main.c @@ -1020,7 +1020,7 @@ typedef struct TestApplication_s dds_entity_t topic; dds_entity_t dr; dds_entity_t dw; - dds_dynamic_type_t *dt; + struct type* dt; dds_topic_descriptor_t* td; } TestApplication; @@ -1061,6 +1061,7 @@ void TestApplication_free(TestApplication *app) bool TestApplication_initialize(TestApplication *app, TestOptions *options) { dds_qos_t* dp_qos = dds_create_qos(); + dds_return_t retcode; if (options->disable_type_info) { @@ -1089,14 +1090,21 @@ bool TestApplication_initialize(TestApplication *app, TestOptions *options) PRINT_TYPEID(app->dt, options->type_object_version); } - if (REGISTER_TYPE(app->dp, app->dt, options->type_name) != DDS_RETCODE_OK) + if (dds_dynamic_type_register(app->dt->dtype, &app->dt->typeinfo) != DDS_RETCODE_OK) { log_message(ERROR, "failed to register type"); return false; } printf("Create topic: %s\n", options->topic_name); - app->topic = dds_create_topic(app->dp, app->dt); + + if (dds_create_topic_descriptor(DDS_FIND_SCOPE_LOCAL_DOMAIN, app->dp, app->dt->typeinfo, 0, &app->td) != DDS_RETCODE_OK) + { + log_message(ERROR, "failed to create topic descriptor"); + return false; + } + + app->topic = dds_create_topic(app->dp, app->td, options->topic_name, NULL, NULL); if (app->topic == 0) { log_message(ERROR, "failed to create topic"); @@ -1388,36 +1396,36 @@ bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options) //------------------------------------------------------------- bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) { - while (!all_done) + while (all_done != 0) { dds_return_t retval; - void* samples = malloc(sizeof(int*) * 10000); + void* samples[10000]; for(int i = 0; i < 10000; i++) { - ((void**)samples)[i] = NULL; + samples[i] = NULL; } dds_sample_info_t* sample_infos = malloc(sizeof(dds_sample_info_t) * 10000); do { retval = dds_take(app->dr, - &samples, + samples, sample_infos, - sizeof(int *) * 10000, + 10000, 10000); if (retval >= 0) { unsigned int i; for (i = 0; i < retval; i++) { - DynamicData *sample = &samples[i]; + void* sample = samples[i]; dds_sample_info_t *sample_info = &sample_infos[i]; if (sample_info->valid_data) { printf("sample_received()\n"); - PRINT_DATA(sample); - if (CHECK_DATA(sample, options->xml_data_uri, options->json_data_uri)) + print_sample(sample_info->valid_data, sample, &app->dt->typeobj->_u.complete); + if (CHECK_DATA(sample, app->dt, options->xml_data_uri, options->json_data_uri)) { printf("Received sample is the same as loaded\n"); } @@ -1426,12 +1434,10 @@ bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) printf("Received sample is not the same as loaded\n"); } } + dds_return_loan(app->dr, &samples[i], 1); } - } - dds_return_loan(app->dr, &samples, 10000 * sizeof(int*)); } while (retval >= 0); - dds_sleepfor(DDS_USECS(100000)); } @@ -1441,14 +1447,8 @@ bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) //------------------------------------------------------------- bool TestApplication_run_publisher(TestApplication *app, TestOptions *options) { - DDS::DynamicData *dd = CREATE_DATA(dt); - if (dd == NULL) - { - log_message(ERROR, "Error creating DynamicData"); - return false; - } - - if (INIT_DATA(dd, options->xml_data_uri, options->json_data_uri) != DDS_RETCODE_OK) + void* dynamic_sample = NULL; + if (INIT_DATA(&dynamic_sample, app->dt, options->xml_data_uri, options->json_data_uri) != DDS_RETCODE_OK) { log_message(ERROR, "Error initializing data"); return false; @@ -1456,16 +1456,15 @@ bool TestApplication_run_publisher(TestApplication *app, TestOptions *options) while (!all_done) { - DynamicDataWriter *ddw = dynamic_cast(dw); - ddw->write(*dd, HANDLE_NIL); + dds_write(app->dw, dynamic_sample); if (options->print_writer_samples) { printf(" Wrote:\n"); - PRINT_DATA(dd); + print_sample(true, dynamic_sample, &app->dt->typeobj->_u.complete); } dds_sleepfor(DDS_USECS(1000000)); } - CLEANUP_DATA(dd); + ddsrt_free(dynamic_sample); return true; } diff --git a/src/c/variant_eclipse_cyclone_dds.h b/src/c/variant_eclipse_cyclone_dds.h index 3c1af7c..e0ce2b1 100644 --- a/src/c/variant_eclipse_cyclone_dds.h +++ b/src/c/variant_eclipse_cyclone_dds.h @@ -1,4 +1,11 @@ #include "dds/dds.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/domtree.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/dynsub.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/print_sample.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/print_type.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/scan_sample.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/type_cache.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/xmltype.h" #define DDS_BOOLEAN_TRUE (1) #define DDS_BOOLEAN_FALSE (0) @@ -38,131 +45,62 @@ const char* get_qos_policy_name(uint32_t last_policy_id) { } } -dds_dynamic_type_t * +struct type* CREATE_TYPE( dds_entity_t dp, - const char * types_uri, - const char * type_name ) + char * types_uri, + char * type_name ) { - dds_dynamic_type_t* dt = NULL; + struct type* xml_type = NULL; if ( dp && types_uri && type_name ) { - DDS::DynamicTypeBuilderFactory * dtbf = - DDS::DynamicTypeBuilderFactoryXml::get_instance( ); - if ( dtbf ) - { - DDS::DynamicTypeBuilder * dtb = - dtbf->create_type_w_uri ( types_uri, - type_name, - NULL ); - if ( dtb ) - { - dt = dtb->build( ); - dtbf->delete_type_builder( dtb ); - } - } + xml_type = dds_type_from_xml(dp, types_uri, type_name); } - return dt; + return xml_type; } dds_return_t -REGISTER_TYPE( dds_entity_t dp, - dds_dynamic_type_t* dt, - const char* type_name ) -{ - dds_return_t retval = DDS_RETCODE_ERROR; - if ( dp && dt && type_name ) - { - DDS::DynamicTypeSupport * dts = - DDS::DynamicTypeSupport::create_type_support ( dt ); - if ( dts ) - { - retval = dts->register_type( dp, type_name ); - } - } - return retval; -} - -void -CLEANUP_TYPE( dds_entity_t dp, - dds_dynamic_type_t* dt ) -{ - if ( dp && dt ) - { - DDS::DynamicTypeBuilderFactory * dtbf = - DDS::DynamicTypeBuilderFactoryXml::get_instance( ); - dtbf->delete_type( dt ); - } -} - -DDS::DynamicData * -CREATE_DATA( DDS::DynamicType * dt ) -{ - DDS::DynamicData * retval = NULL; - DDS::DynamicDataFactory * ddf = DDS::DynamicDataFactory::get_instance(); - if ( ddf ) - { - retval = ddf->create_data( dt ); - } - return retval; -} - -DDS::ReturnCode_t -INIT_DATA( DDS::DynamicData * dd, +INIT_DATA( void ** dd, + struct type * dt, const char * xml_data_uri, const char * json_data_uri ) { - DDS::ReturnCode_t retval = DDS::RETCODE_ERROR; + dds_return_t retval = DDS_RETCODE_ERROR; if ( dd ) { fflush( stderr ); if ( xml_data_uri ) { - retval = coredx::DynamicData_init_from_xmluri( dd, xml_data_uri ); + struct elem* input = domtree_from_file( xml_data_uri ); + *dd = scan_sample(input, &dt->typeobj->_u.complete); + if (*dd){ + retval = DDS_RETCODE_OK; + } } else { /* no specific data, just init to 'defaults' */ fprintf( stderr, "[ No data to load. Using empty sample... ]\n" ); fflush( stderr ); - retval = DDS::RETCODE_OK; + retval = DDS_RETCODE_ERROR; } } return retval; } - -void -PRINT_DATA( DDS::DynamicData * dd ) -{ - // coredx::DynamicData_print( stderr, dd, 0 ); - coredx::DynamicData_print_xml( stdout, dd, 0 ); -} -void CLEANUP_DATA(DDS::DynamicData *dd) -{ - DDS::DynamicDataFactory * ddf = DDS::DynamicDataFactory::get_instance(); - ddf->delete_data( dd ); -} - - -bool -CHECK_DATA(DDS::DynamicData *dd, - const char *xml_data_uri, - const char *json_data_uri) +bool CHECK_DATA(void *dynamic_sample, + struct type *dt, + const char *xml_data_uri, + const char *json_data_uri) { bool retval = false; - if (dd == NULL && json_data_uri == NULL) { + if (dynamic_sample == NULL && xml_data_uri == NULL) { return retval; } - DDS::DynamicData *data_check = - CREATE_DATA( (DDS::DynamicType *) dd->get_type() ); - - if (data_check == NULL) { - retval = false; - goto done; - } - if (INIT_DATA(data_check, xml_data_uri, json_data_uri) != DDS_RETCODE_OK) { + void* data_check = NULL; + + if (INIT_DATA(&data_check, dt, xml_data_uri, json_data_uri) != DDS_RETCODE_OK) { retval = false; goto done; } @@ -171,12 +109,12 @@ CHECK_DATA(DDS::DynamicData *dd, if ( !retval ) { printf("Expected:\n"); - PRINT_DATA( data_check ); + print_sample( true, data_check, &dt->typeobj->_u.complete ); } done: if (data_check != NULL) { - CLEANUP_DATA(data_check); + ddsrt_free(data_check); } return retval; } From b488c7ce21071509d53ddb0f487e4723cf1d7530 Mon Sep 17 00:00:00 2001 From: disganaitis Date: Mon, 16 Mar 2026 09:44:38 +0000 Subject: [PATCH 3/8] Basic working implementation pre-bugfixes --- generate_xlsx_report.py | 4 +++ src/c/cyclone-dds-cmake/CMakeLists.txt | 19 +++++++++-- src/c/test_main.c | 44 ++++++++++++++++++-------- src/c/variant_eclipse_cyclone_dds.h | 26 +++++++++++++-- 4 files changed, 76 insertions(+), 17 deletions(-) diff --git a/generate_xlsx_report.py b/generate_xlsx_report.py index a70652e..4084e7d 100644 --- a/generate_xlsx_report.py +++ b/generate_xlsx_report.py @@ -63,6 +63,8 @@ def get_company_name(product:str) -> str: return 'eProsima' elif 'dust' in product.lower(): return 'S2E Software Systems' + elif 'cyclone' in product.lower(): + return 'Eclipse Foundation' else: raise RuntimeError('Impossible to get company name: ' + product) @@ -82,6 +84,8 @@ def get_product_name(product:str) -> str: return 'FastDDS ' + re.search(r'([\d.]+)', product).group(1) elif 'dust_dds' in product.lower(): return 'Dust DDS ' + re.search(r'([\d.]+)', product).group(1) + elif 'cyclone' in product.lower(): + return 'Cyclone DDS' else: raise RuntimeError('Impossible to get product name: ' + product) diff --git a/src/c/cyclone-dds-cmake/CMakeLists.txt b/src/c/cyclone-dds-cmake/CMakeLists.txt index 1da40b6..62b89c2 100644 --- a/src/c/cyclone-dds-cmake/CMakeLists.txt +++ b/src/c/cyclone-dds-cmake/CMakeLists.txt @@ -5,8 +5,23 @@ project(shape LANGUAGES C) find_package(CycloneDDS REQUIRED) set(EXECUTABLE_NAME "eclipse_cyclone-${CycloneDDS_VERSION}_linux") -add_executable(${EXECUTABLE_NAME} ../test_main.c) +add_executable(${EXECUTABLE_NAME} ../test_main.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/domtree.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/domtree.h + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/type_cache.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/type_cache.h + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_sample.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_sample.h + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_type.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_type.h + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/compare_samples.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/compare_samples.h + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/scan_sample.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/scan_sample.h + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/xmltype.c + ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/xmltype.h + ) target_compile_definitions(${EXECUTABLE_NAME} PUBLIC -DCYCLONE_DDS) -target_link_libraries(${EXECUTABLE_NAME} shape_lib CycloneDDS::ddsc m) +target_link_libraries(${EXECUTABLE_NAME} CycloneDDS::ddsc m) diff --git a/src/c/test_main.c b/src/c/test_main.c index 6a9de34..944ecae 100644 --- a/src/c/test_main.c +++ b/src/c/test_main.c @@ -166,7 +166,7 @@ static char* to_string_type_consistency(dds_type_consistency_kind_t consistency_ } /*************************************************************/ -Verbosity verbosity = ERROR; +Verbosity verbosity = DEBUG; void log_message(Verbosity level_verbosity, const char *format, ...) { @@ -289,6 +289,8 @@ TestOptions TestOptions_create() options.disable_type_info = false; options.type_object_version = 2; options.print_typeid = false; + + return options; } //------------------------------------------------------------- @@ -429,7 +431,7 @@ bool TestOptions_parse(TestOptions *options, int argc, char *argv[]) } case 'e': { - verbosity = ERROR; + verbosity = DEBUG; break; } default: @@ -578,11 +580,13 @@ bool TestOptions_parse(TestOptions *options, int argc, char *argv[]) } case 'P': { + //printf("Publishing samples: %c\n", optarg[0]); options->publish = true; break; } case 'S': { + //printf("Subscribing samples: %c\n", optarg[0]); options->subscribe = true; break; } @@ -1060,6 +1064,22 @@ void TestApplication_free(TestApplication *app) //------------------------------------------------------------- bool TestApplication_initialize(TestApplication *app, TestOptions *options) { + app->dp_listener = dds_create_listener(NULL); + dds_lset_inconsistent_topic(app->dp_listener, on_inconsistent_topic); + dds_lset_offered_incompatible_qos(app->dp_listener, on_offered_incompatible_qos); + dds_lset_publication_matched(app->dp_listener, on_publication_matched); + dds_lset_offered_deadline_missed(app->dp_listener, on_offered_deadline_missed); + dds_lset_liveliness_lost(app->dp_listener, on_liveliness_lost); + dds_lset_requested_incompatible_qos(app->dp_listener, on_requested_incompatible_qos); + dds_lset_subscription_matched(app->dp_listener, on_subscription_matched); + dds_lset_requested_deadline_missed(app->dp_listener, on_requested_deadline_missed); + dds_lset_liveliness_changed(app->dp_listener, on_liveliness_changed); + dds_lset_sample_rejected(app->dp_listener, on_sample_rejected); + dds_lset_data_available(app->dp_listener, on_data_available); + dds_lset_sample_lost(app->dp_listener,on_sample_lost); + dds_lset_data_on_readers(app->dp_listener, on_data_on_readers); + + dds_qos_t* dp_qos = dds_create_qos(); dds_return_t retcode; @@ -1070,7 +1090,7 @@ bool TestApplication_initialize(TestApplication *app, TestOptions *options) //set_type_object_version(dp_qos, options->type_object_version); - app->dp = dds_create_participant(options->domain_id, dp_qos, NULL); + app->dp = dds_create_participant(options->domain_id, dp_qos, app->dp_listener); if (app->dp == 0) { log_message(ERROR, "failed to create participant (missing license?)."); @@ -1090,11 +1110,11 @@ bool TestApplication_initialize(TestApplication *app, TestOptions *options) PRINT_TYPEID(app->dt, options->type_object_version); } - if (dds_dynamic_type_register(app->dt->dtype, &app->dt->typeinfo) != DDS_RETCODE_OK) - { - log_message(ERROR, "failed to register type"); - return false; - } + //if ((retcode = dds_dynamic_type_register(app->dt->dtype, &app->dt->typeinfo)) != DDS_RETCODE_OK) + //{ + // log_message(ERROR, "failed to register type: %s", dds_strretcode(retcode)); + // return false; + //} printf("Create topic: %s\n", options->topic_name); @@ -1396,7 +1416,7 @@ bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options) //------------------------------------------------------------- bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) { - while (all_done != 0) + while (!all_done) { dds_return_t retval; void* samples[10000]; @@ -1473,15 +1493,13 @@ int main(int argc, char *argv[]) { install_sig_handlers(); - TestOptions options; - TestOptions_create(&options); + TestOptions options = TestOptions_create(); bool parseResult = TestOptions_parse(&options, argc, argv); if (!parseResult) { exit(ERROR_PARSING_ARGUMENTS); } - TestApplication testApp; - TestApplication_create(&testApp); + TestApplication testApp = TestApplication_create(); if (!TestApplication_initialize(&testApp, &options)) { exit(ERROR_INITIALIZING); diff --git a/src/c/variant_eclipse_cyclone_dds.h b/src/c/variant_eclipse_cyclone_dds.h index e0ce2b1..85c857e 100644 --- a/src/c/variant_eclipse_cyclone_dds.h +++ b/src/c/variant_eclipse_cyclone_dds.h @@ -2,7 +2,9 @@ #include "dds/../../share/CycloneDDS/examples/dynsub/domtree.h" #include "dds/../../share/CycloneDDS/examples/dynsub/dynsub.h" #include "dds/../../share/CycloneDDS/examples/dynsub/print_sample.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/compare_samples.h" #include "dds/../../share/CycloneDDS/examples/dynsub/print_type.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/type_cache.h" #include "dds/../../share/CycloneDDS/examples/dynsub/scan_sample.h" #include "dds/../../share/CycloneDDS/examples/dynsub/type_cache.h" #include "dds/../../share/CycloneDDS/examples/dynsub/xmltype.h" @@ -105,9 +107,10 @@ bool CHECK_DATA(void *dynamic_sample, goto done; } - retval = dd->equals(data_check); - if ( !retval ) + retval = compare_samples(true, dynamic_sample, data_check, &dt->typeobj->_u.complete); + if ( retval <= 0 ) { + printf("%d: ", retval); printf("Expected:\n"); print_sample( true, data_check, &dt->typeobj->_u.complete ); } @@ -118,3 +121,22 @@ bool CHECK_DATA(void *dynamic_sample, } return retval; } + +void +CLEANUP_TYPE( dds_entity_t dp, + struct type* dt ) +{ + if ( dp && dt ) + { + dds_free_xml_type(dt); + } +} + +void PRINT_TYPEID(struct type *dt, int version) { + const DDS_XTypes_EquivalenceHash *id = &((DDS_XTypes_TypeInformation *)dt->typeinfo)->complete.typeid_with_size.type_id._u.equivalence_hash; + printf("Type Object V%d - Type ID: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", version, + (unsigned) (*id)[0], (unsigned) (*id)[1], (unsigned) (*id)[2], (unsigned) (*id)[3], + (unsigned) (*id)[4], (unsigned) (*id)[5], (unsigned) (*id)[6], (unsigned) (*id)[7], + (unsigned) (*id)[8], (unsigned) (*id)[9], (unsigned) (*id)[10], (unsigned) (*id)[11], + (unsigned) (*id)[12], (unsigned) (*id)[13]); +} \ No newline at end of file From 9559d7860452a05c428d3f3e5af2fd1bc15fa1aa Mon Sep 17 00:00:00 2001 From: disganaitis Date: Mon, 16 Mar 2026 17:29:33 +0000 Subject: [PATCH 4/8] Rerouted certain incompatible QoS to inconsistent topic as cyclone dds doesn't have support for it yet, but it seems to mostly do the trick as this isn't a QoS test --- src/c/test_main.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/c/test_main.c b/src/c/test_main.c index 944ecae..8d49101 100644 --- a/src/c/test_main.c +++ b/src/c/test_main.c @@ -915,6 +915,13 @@ void on_inconsistent_topic(dds_entity_t topic, const dds_inconsistent_topic_stat void on_offered_incompatible_qos(dds_entity_t dw, const dds_offered_incompatible_qos_status_t status, void* args) { + if (status.last_policy_id == DDS_TYPE_CONSISTENCY_ENFORCEMENT_QOS_POLICY_ID){ + dds_inconsistent_topic_status_t topic_status; + topic_status.total_count = 0; + topic_status.total_count_change = 0; + on_inconsistent_topic(dds_get_topic(dw), topic_status, args); + return; + } dds_entity_t topic = dds_get_topic(dw); char* topic_name = helper_get_topic_name(topic); char* type_name = helper_get_type_name(topic); @@ -963,6 +970,13 @@ void on_liveliness_lost(dds_entity_t dw, const dds_liveliness_lost_status_t stat void on_requested_incompatible_qos(dds_entity_t dr, const dds_requested_incompatible_qos_status_t status, void* args) { + if (status.last_policy_id == DDS_TYPE_CONSISTENCY_ENFORCEMENT_QOS_POLICY_ID){ + dds_inconsistent_topic_status_t topic_status; + topic_status.total_count = 0; + topic_status.total_count_change = 0; + on_inconsistent_topic(dds_get_topic(dr), topic_status, args); + return; + } dds_entity_t topic = dds_get_topic(dr); char* topic_name = helper_get_topic_name(topic); char* type_name = helper_get_type_name(topic); @@ -1255,6 +1269,38 @@ bool TestApplication_init_publisher(TestApplication *app, TestOptions *options) } } + dds_qset_type_consistency( + dw_qos, + options->type_consistency_kind, + options->ignore_sequence_bounds, + options->ignore_string_bounds, + options->ignore_member_names, + options->prevent_type_widening, + options->force_type_validation); + { + dds_type_consistency_kind_t type_consistency_kind; + bool ignore_sequence_bounds; + bool ignore_string_bounds; + bool ignore_member_names; + bool prevent_type_widening; + bool force_type_validation; + + dds_qget_type_consistency( + dw_qos, + &type_consistency_kind, + &ignore_sequence_bounds, + &ignore_string_bounds, + &ignore_member_names, + &prevent_type_widening, + &force_type_validation); + log_message(DEBUG, " TypeConsistency * kind = %s", to_string_type_consistency(type_consistency_kind)); + log_message(DEBUG, " * ignore_sequence_bounds = %d", ignore_sequence_bounds); + log_message(DEBUG, " * ignore_string_bounds = %d", ignore_string_bounds); + log_message(DEBUG, " * ignore_member_names = %d", ignore_member_names); + log_message(DEBUG, " * prevent_type_widening = %d", prevent_type_widening); + log_message(DEBUG, " * force_type_validation = %d", force_type_validation); + } + printf("Create writer for topic: %s type: %s\n", options->topic_name, options->type_name); app->dw = dds_create_writer(app->pub, app->topic, dw_qos, NULL); From 79a2f70b3050aa3af772859c558fc92826bbc352 Mon Sep 17 00:00:00 2001 From: disganaitis Date: Thu, 19 Mar 2026 14:19:02 +0000 Subject: [PATCH 5/8] Fixed incorect ignore_sequence/string_bounds default settings --- src/c/test_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/c/test_main.c b/src/c/test_main.c index 8d49101..492c240 100644 --- a/src/c/test_main.c +++ b/src/c/test_main.c @@ -695,7 +695,7 @@ bool TestOptions_parse(TestOptions *options, int argc, char *argv[]) options->ignore_sequence_bounds = DDS_BOOLEAN_FALSE; break; case 'd': - options->ignore_sequence_bounds = DDS_BOOLEAN_FALSE; + options->ignore_sequence_bounds = DDS_BOOLEAN_TRUE; break; default: log_message(ERROR, "unrecognized value for type_consistency." @@ -719,7 +719,7 @@ bool TestOptions_parse(TestOptions *options, int argc, char *argv[]) options->ignore_string_bounds = DDS_BOOLEAN_FALSE; break; case 'd': - options->ignore_string_bounds = DDS_BOOLEAN_FALSE; + options->ignore_string_bounds = DDS_BOOLEAN_TRUE; break; default: log_message(ERROR, "unrecognized value for type_consistency." From 2155da8e911073d10fd579e4fd9e920aed27be98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20I=C5=A1ganaitis?= Date: Thu, 2 Apr 2026 06:55:40 +0000 Subject: [PATCH 6/8] Update to match cleaned up version of try-construct and xml library --- src/c/cyclone-dds-cmake/CMakeLists.txt | 28 +++++++-------- src/c/test_main.c | 40 ++++++++++++++++------ src/c/variant_eclipse_cyclone_dds.h | 47 +++++++------------------- 3 files changed, 57 insertions(+), 58 deletions(-) diff --git a/src/c/cyclone-dds-cmake/CMakeLists.txt b/src/c/cyclone-dds-cmake/CMakeLists.txt index 62b89c2..2c01a2e 100644 --- a/src/c/cyclone-dds-cmake/CMakeLists.txt +++ b/src/c/cyclone-dds-cmake/CMakeLists.txt @@ -6,20 +6,20 @@ find_package(CycloneDDS REQUIRED) set(EXECUTABLE_NAME "eclipse_cyclone-${CycloneDDS_VERSION}_linux") add_executable(${EXECUTABLE_NAME} ../test_main.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/domtree.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/domtree.h - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/type_cache.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/type_cache.h - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_sample.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_sample.h - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_type.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/print_type.h - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/compare_samples.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/compare_samples.h - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/scan_sample.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/scan_sample.h - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/xmltype.c - ~/eboasson-cyclonedds/install/share/CycloneDDS/examples/dynsub/xmltype.h + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/dyntypelib.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/dyntypelib.h + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/domtree.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/domtree.h + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/type_cache.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/type_cache.h + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/print_sample.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/print_type.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/print_type.h + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/compare_samples.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/compare_samples.h + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/scan_sample.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/size_and_align.c + ${CMAKE_PREFIX_PATH}/share/CycloneDDS/examples/dynsub/size_and_align.h ) target_compile_definitions(${EXECUTABLE_NAME} PUBLIC -DCYCLONE_DDS) diff --git a/src/c/test_main.c b/src/c/test_main.c index 492c240..0d986d0 100644 --- a/src/c/test_main.c +++ b/src/c/test_main.c @@ -1038,7 +1038,10 @@ typedef struct TestApplication_s dds_entity_t topic; dds_entity_t dr; dds_entity_t dw; - struct type* dt; + + struct dyntypelib *dtl; + struct dyntypelib_error err; + struct dyntype* dt; dds_topic_descriptor_t* td; } TestApplication; @@ -1059,7 +1062,9 @@ TestApplication TestApplication_create() app.topic = 0; app.dr = 0; app.dw = 0; + app.dtl = NULL; app.dt = NULL; + app.td = NULL; return app; } @@ -1070,7 +1075,7 @@ void TestApplication_free(TestApplication *app) if (app->dp_listener) dds_delete_listener(app->dp_listener); if (app->dt) - CLEANUP_TYPE(app->dp, app->dt); + dtl_free(app->dtl); if (app->dp) dds_delete(app->dp); } @@ -1111,8 +1116,17 @@ bool TestApplication_initialize(TestApplication *app, TestOptions *options) return false; } log_message(DEBUG, "Participant created"); + + app->dtl = dtl_new(app->dp); + dtl_set_print_types (app->dtl, true); + if (dtl_add_xml_type_library (app->dtl, options->types_uri, &app->err) != DDS_RETCODE_OK) + { + log_message(ERROR, "failed to create type"); + log_message(DEBUG, "errmsg: %s", app->err.errmsg); + return false; + } - app->dt = CREATE_TYPE(app->dp, options->types_uri, options->type_name); + app->dt = dtl_lookup_typename(app->dtl, options->type_name); if (app->dt == NULL) { log_message(ERROR, "failed to create type"); @@ -1139,7 +1153,7 @@ bool TestApplication_initialize(TestApplication *app, TestOptions *options) } app->topic = dds_create_topic(app->dp, app->td, options->topic_name, NULL, NULL); - if (app->topic == 0) + if (app->topic < 0) { log_message(ERROR, "failed to create topic"); return false; @@ -1166,7 +1180,6 @@ bool TestApplication_run(TestApplication *app, TestOptions *options) { return TestApplication_run_subscriber(app, options); } - CLEANUP_TYPE(app->dp, app->dt); return false; } @@ -1305,12 +1318,15 @@ bool TestApplication_init_publisher(TestApplication *app, TestOptions *options) app->dw = dds_create_writer(app->pub, app->topic, dw_qos, NULL); - if (app->dw == 0) + if (app->dw < 0) { log_message(ERROR, "failed to create datawriter"); return false; } + size_t align, size; + build_typecache_to (app->dtl->typecache, &app->dt->typeobj->_u.complete, &align, &size); + log_message(DEBUG, "Data Writer created"); return true; @@ -1455,6 +1471,9 @@ bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options) return false; } + size_t align, size; + build_typecache_to (app->dtl->typecache, &app->dt->typeobj->_u.complete, &align, &size); + log_message(DEBUG, "Data Reader created"); return true; } @@ -1462,6 +1481,7 @@ bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options) //------------------------------------------------------------- bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) { + log_message(DEBUG, "Run subscriber"); while (!all_done) { dds_return_t retval; @@ -1490,8 +1510,8 @@ bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) if (sample_info->valid_data) { printf("sample_received()\n"); - print_sample(sample_info->valid_data, sample, &app->dt->typeobj->_u.complete); - if (CHECK_DATA(sample, app->dt, options->xml_data_uri, options->json_data_uri)) + dtl_print_sample(app->dtl, sample_info->valid_data, sample, &app->dt->typeobj->_u.complete); + if (CHECK_DATA(sample, app->dtl, app->dt, options->xml_data_uri, options->json_data_uri)) { printf("Received sample is the same as loaded\n"); } @@ -1514,7 +1534,7 @@ bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) bool TestApplication_run_publisher(TestApplication *app, TestOptions *options) { void* dynamic_sample = NULL; - if (INIT_DATA(&dynamic_sample, app->dt, options->xml_data_uri, options->json_data_uri) != DDS_RETCODE_OK) + if (INIT_DATA(&dynamic_sample, app->dtl, app->dt, options->xml_data_uri, options->json_data_uri) != DDS_RETCODE_OK) { log_message(ERROR, "Error initializing data"); return false; @@ -1526,7 +1546,7 @@ bool TestApplication_run_publisher(TestApplication *app, TestOptions *options) if (options->print_writer_samples) { printf(" Wrote:\n"); - print_sample(true, dynamic_sample, &app->dt->typeobj->_u.complete); + dtl_print_sample(app->dtl, true, dynamic_sample, &app->dt->typeobj->_u.complete); } dds_sleepfor(DDS_USECS(1000000)); } diff --git a/src/c/variant_eclipse_cyclone_dds.h b/src/c/variant_eclipse_cyclone_dds.h index 85c857e..4f4c878 100644 --- a/src/c/variant_eclipse_cyclone_dds.h +++ b/src/c/variant_eclipse_cyclone_dds.h @@ -1,13 +1,11 @@ #include "dds/dds.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/dyntypelib.h" #include "dds/../../share/CycloneDDS/examples/dynsub/domtree.h" #include "dds/../../share/CycloneDDS/examples/dynsub/dynsub.h" -#include "dds/../../share/CycloneDDS/examples/dynsub/print_sample.h" #include "dds/../../share/CycloneDDS/examples/dynsub/compare_samples.h" #include "dds/../../share/CycloneDDS/examples/dynsub/print_type.h" #include "dds/../../share/CycloneDDS/examples/dynsub/type_cache.h" -#include "dds/../../share/CycloneDDS/examples/dynsub/scan_sample.h" -#include "dds/../../share/CycloneDDS/examples/dynsub/type_cache.h" -#include "dds/../../share/CycloneDDS/examples/dynsub/xmltype.h" +#include "dds/../../share/CycloneDDS/examples/dynsub/size_and_align.h" #define DDS_BOOLEAN_TRUE (1) #define DDS_BOOLEAN_FALSE (0) @@ -47,22 +45,11 @@ const char* get_qos_policy_name(uint32_t last_policy_id) { } } -struct type* -CREATE_TYPE( dds_entity_t dp, - char * types_uri, - char * type_name ) -{ - struct type* xml_type = NULL; - if ( dp && types_uri && type_name ) - { - xml_type = dds_type_from_xml(dp, types_uri, type_name); - } - return xml_type; -} dds_return_t INIT_DATA( void ** dd, - struct type * dt, + struct dyntypelib * dtl, + struct dyntype * dt, const char * xml_data_uri, const char * json_data_uri ) { @@ -73,7 +60,8 @@ INIT_DATA( void ** dd, if ( xml_data_uri ) { struct elem* input = domtree_from_file( xml_data_uri ); - *dd = scan_sample(input, &dt->typeobj->_u.complete); + struct dyntypelib_error err; + *dd = dtl_scan_sample(dtl, input, &dt->typeobj->_u.complete, true, &err); if (*dd){ retval = DDS_RETCODE_OK; } @@ -90,7 +78,8 @@ INIT_DATA( void ** dd, } bool CHECK_DATA(void *dynamic_sample, - struct type *dt, + struct dyntypelib *dtl, + struct dyntype *dt, const char *xml_data_uri, const char *json_data_uri) { @@ -102,17 +91,17 @@ bool CHECK_DATA(void *dynamic_sample, void* data_check = NULL; - if (INIT_DATA(&data_check, dt, xml_data_uri, json_data_uri) != DDS_RETCODE_OK) { + if (INIT_DATA(&data_check, dtl, dt, xml_data_uri, json_data_uri) != DDS_RETCODE_OK) { retval = false; goto done; } - retval = compare_samples(true, dynamic_sample, data_check, &dt->typeobj->_u.complete); + retval = compare_samples(dtl->typecache, true, dynamic_sample, data_check, &dt->typeobj->_u.complete); if ( retval <= 0 ) { printf("%d: ", retval); printf("Expected:\n"); - print_sample( true, data_check, &dt->typeobj->_u.complete ); + dtl_print_sample(dtl, true, data_check, &dt->typeobj->_u.complete ); } done: @@ -122,21 +111,11 @@ bool CHECK_DATA(void *dynamic_sample, return retval; } -void -CLEANUP_TYPE( dds_entity_t dp, - struct type* dt ) -{ - if ( dp && dt ) - { - dds_free_xml_type(dt); - } -} - -void PRINT_TYPEID(struct type *dt, int version) { +void PRINT_TYPEID(struct dyntype *dt, int version) { const DDS_XTypes_EquivalenceHash *id = &((DDS_XTypes_TypeInformation *)dt->typeinfo)->complete.typeid_with_size.type_id._u.equivalence_hash; printf("Type Object V%d - Type ID: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", version, (unsigned) (*id)[0], (unsigned) (*id)[1], (unsigned) (*id)[2], (unsigned) (*id)[3], (unsigned) (*id)[4], (unsigned) (*id)[5], (unsigned) (*id)[6], (unsigned) (*id)[7], (unsigned) (*id)[8], (unsigned) (*id)[9], (unsigned) (*id)[10], (unsigned) (*id)[11], (unsigned) (*id)[12], (unsigned) (*id)[13]); -} \ No newline at end of file +} From 02fc0398aba997f5d80f46cc2e1131cb13ebbd34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20I=C5=A1ganaitis?= Date: Mon, 13 Apr 2026 08:17:31 +0000 Subject: [PATCH 7/8] set ownership explicitly, fix check for returned sample count --- src/c/test_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/c/test_main.c b/src/c/test_main.c index 0d986d0..1903c15 100644 --- a/src/c/test_main.c +++ b/src/c/test_main.c @@ -1383,6 +1383,9 @@ bool TestApplication_init_subscriber(TestApplication *app, TestOptions *options) { dds_qset_ownership(dr_qos, DDS_OWNERSHIP_EXCLUSIVE); dds_qset_ownership_strength(dr_qos, options->ownership_strength); + } else + { + dds_qset_ownership(dr_qos, DDS_OWNERSHIP_SHARED); } { dds_ownership_kind_t ownership; @@ -1499,7 +1502,7 @@ bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) sample_infos, 10000, 10000); - if (retval >= 0) + if (retval > 0) { unsigned int i; for (i = 0; i < retval; i++) @@ -1523,7 +1526,7 @@ bool TestApplication_run_subscriber(TestApplication *app, TestOptions *options) dds_return_loan(app->dr, &samples[i], 1); } } - } while (retval >= 0); + } while (retval > 0); dds_sleepfor(DDS_USECS(100000)); } From 0a2fd5c0941e93ddd1cc1e928d3a73e6c677c53f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20I=C5=A1ganaitis?= Date: Mon, 13 Apr 2026 09:21:33 +0000 Subject: [PATCH 8/8] Adding Rocket Software CLA --- CLA/CLA_Rocket_Software.md | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 CLA/CLA_Rocket_Software.md diff --git a/CLA/CLA_Rocket_Software.md b/CLA/CLA_Rocket_Software.md new file mode 100644 index 0000000..010e6d4 --- /dev/null +++ b/CLA/CLA_Rocket_Software.md @@ -0,0 +1,61 @@ +# OMG DDS INTEROPERABILITY REPOSITORY - CONTRIBUTOR LICENSE AGREEMENT + +**This Contributor License Agreement ("Agreement") specifies the terms under which the individual or corporate entity specified in the signature block below (“You”) agree to make intellectual property contributions to the OMG DDS Interoperability Repository. BY SIGNING BELOW YOU ARE AGREEING TO BE BOUND BY THE TERMS OF THIS AGREEMENT. If You are signing this Agreement in Your capacity as an employee, THEN YOUR EMPLOYER AND YOU ARE BOTH BOUND BY THIS AGREEMENT.** + +1. Definitions + + 1. "OMG DDS Xtypes Interoperability Repository" (or “Repository”) means the Git repository [https://github.com/omg-dds/dds-xtypes](https://github.com/omg-dds/dds-xtypes). + + 2. "Moderator" means an entity or individual responsible for authorizing changes to the Repository. + + 3. "Submit" (or “Submitted”) means any submission, including source code, binaries, code, pull requests, issue reports, comments, etc., made to the Moderators for inclusion in the Repository either through the Git repository interface or through electronic file transfer. + + 4. A "Contribution" is any original work of authorship, including any modifications or additions to an existing work, that You Submit to the DDS Interoperability Repository. + + 5. A "User" is anyone who accesses the Repository. + +2. Allowable Contribution Representations + + 1. You represent that You have the necessary rights to the Contribution(s) to meet the obligations of this Agreement. If You are employed, Your employer has authorized Contribution(s) under this Agreement. + + 2. You represent that you have no knowledge of third-party intellectual property rights that are likely to be infringed by the Contribution(s). You represent that you have no knowledge that such infringement or any allegation of misappropriation of intellectual property rights is likely to be claimed or has already been claimed. + +3. License + + You grant Moderators a perpetual, worldwide, non-exclusive, assignable, paid-up license to publish, display, and redistribute the Contribution as part of the Repository. You also license to Moderators under the same terms any other intellectual property rights required to publish, display, and redistribute the Contributions as part of the Repository. You further grant all Users of the Repository a license to the Contribution under the terms of the [OMG DDS Interoperability Testing License](../LICENSE.md) included in the Repository. Moderators are under no obligation to publish Contributions. + +4. No Warranty, Consequential Damages. Limited Liability + + Other than explicitly stated herein, You provide the Contribution(s) "as is" with no warranty nor claims of fitness to any purpose. Neither party shall be liable for consequential or special damages of any kind. Other than for breach of warranty or representations herein, the liability of either party to the other shall be limited to $1000. + +5. General + + 1. If You are an agency of the United States Government, then this Agreement will be governed by the United States federal common law. Otherwise, this Agreement will be governed by the laws of the State of California except with regard to its choice of law rules. + + 2. A party may assign this Agreement to an entity acquiring essentially all of the party’s relevant business. + +6. Electronic Signatures + + "Electronic Signature" means any electronic sound, symbol, or process attached to or logically associated with a record and executed and adopted by a party with the intent to sign such record. + + Each party agrees that the Electronic Signatures, whether digital or encrypted, of the parties included in this Agreement are intended to authenticate this writing and to have the same force and effect as manual signatures. + + +IN WITNESS WHEREOF, You, intending to be legally bound, have executed this Agreement or caused Your employer’s proper and duly authorized officer to execute and deliver this Agreement, for good and valuable consideration, the sufficiency of which is hereby acknowledged, as of the day and year first written below. + +* +**For:** + +Entity Name: Rocket Software + +Address: 77 4th Avenue, Waltham, MA 02451, USA + + ("**You**") + +**By:** + +Name: Puneet Kohli + +Title: President, Application Modernization + +Date: March 20, 2026