RTI Connext DDS代码生成器

news2024/11/18 10:47:47

0 简介

RTI®代码生成器Code Generator,创建用RTI Connext®DDS定义define和注册register用户数据类型所需的代码。

在以下情况下,使用代码生成器是可选的:

  • 您正在使用动态类型(请参阅RTI Connext DDS核心库用户手册[RTI ConnextDDS Core Libraries Users Manual]中的“管理内置类型的内存”(第3.2.7节))。

  • 您正在使用一种内置类型(请参阅RTI Connext DDS核心库用户手册[RTI ConnextDDS Core Libraries Users Manual]中的内置数据类型(第3.2节))。

要使用代码生成器Code Generator,您需要在IDL或XML文件中提供数据类型的描述。可以在同一类型定义文件中定义多个数据类型。有关这些文件的详细信息,请参阅RTIConnext DDS核心库用户手册[RTI Connext DDS CoreLibraries Users Manual](第3.3节和第3.4节)。

1 常用路径

1.1 <NDDSHOME>

这是指RTI®Connext®DDS的安装目录。默认安装路径为:

  • macOSsystems:

/Applications/rti_connext_dds-6.1.1

  • Linuxsystems, non-root user:

/home/<youruser name>/rti_connext_dds-6.1.1

  • Linux systems,root user:

/opt/rti_connext_dds-6.1.1

  • Windowssystems, user without Administrator privileges:

<yourhome directory>\rti_connext_dds-6.1.1

  • Windowssystems, user with Administrator privileges:

C:\ProgramFiles\rti_connext_dds-6.1.1

您还可以看到$NDDSHOME或%NDDSHOME%,它是指设置到安装路径的环境变量。

无论您在路径中看到<NDDSHOME>,请将其替换为安装路径。

Windows用户注意:使用命令提示符输入包含路径C:\Program Files(或任何有空格的目录名)的命令时,请将路径括在引号中。例如:

“C:\ProgramFiles\rti_connext_dds6.1.1\bin\rtiddsgen”

或者如果已定义NDDSHOME环境变量:

“%NDDSHOME%\bin\rtiddsgen”

1.2 <pathto examples>

默认情况下,当您第一次运行RTI Launcher或<NDDSHOME>/bin中的任何脚本时,会将示例复制到主目录中。本文档将复制示例的位置称为

<path to examples >。

无论您在哪里看到<path toexamples>,请将其替换为适当的路径。

示例的默认路径:

  • macOS系统:/Users/<用户名>/rti_workspace/6.1.1/examples

  • Linux系统:/home/<用户名>/rti_workspace/6.1.1/example

  • Windows系统:<您的Windows文档文件夹>\rti_workspace\6.1.1\examples其中“您的Windows文件文件夹”取决于您的Windows版本。例如,在Windows 10上,文件夹为C:\Users\<用户名>\Documents。

注意:您可以为rti_workspace指定不同的位置。还可以指定不希望将示例复制到工作空间。有关详细信息,请参阅《RTI Connext DDS安装指南》中的“控制RTI工作区位置和复制示例”。

2 rtiddsgen的命令行参数

在Windows系统上:在运行rtiddsgen之前,请在运行rtiddsgen所使用的同一命令提示符中运行适用于您的体系结构的“vcvars”批处理文件。例如:

vcvarsall.batx86。

“vcvars”批处理文件的位置因您的Visual Studio版本而异。有关安装的确切位置和参数,请参阅MicrosoftVisual Studio文档。或者,从Visual Studio Tools文件夹下的Visual Studio命令提示符运行rtiddsgen。或者,使用命令行参数ppDisable。请参见第6页表3.1rtiddsgen选项中的-ppDisable。

如果要为Connext DDS生成代码,则选项如下:

rtiddsgen [-help]

[-allocateWithMalloc]

[-alwaysUseStdVector]

[-autoGenFiles <architecture>]

[-constructor]

[-create <typefiles| examplefiles|makefiles>]

[-convertToIdl | -convertToXML | -convertToXsd]

[-D <name>[=<value>]]

[-d <outdir>]

[-disableXSDValidation]

[-dllExportMacroSuffix <suffix>]

[-dotnet <modern|legacy>]

[-enableEscapeChar]

[-example <architecture>]

[-exampleTemplate]

[-I <directory>]

[[-inputIdl] <IDLInputFile.idl> | [-inputXml] <XMLInputFile.xml>

|[-inputXsd <IDLInputFile.idl>]]

[-language <Ada|C|C++|C++11|C++/CLI|C#|Java>]

[-namespace]

[-obfuscate]

[-optimization <level>]

[-package <packagePrefix>]

[-platform <architecture>]

[-ppDisable]

[-ppPath <path to preprocessor>]

[-ppOption <option>]

[-qualifiedEnumerator]

[-reader]

[-replace]

[-sequenceSize <unbounded sequences size>]

[-sharedLib]

[-showTemplates]

[-strict]

[-stringSize <unbounded strings size>]

[-typeSequenceSuffix <suffix>]

[-U <name>]

[-unboundedSupport]

[-update <typefiles| examplefiles|makefiles>]

[-use52Keyhash]

[-use526Keyhash]

[-useStdString]

[-V <name< [=<value>]]

[-verbosity [1-3]]

[-version]

[-virtualDestructor]

[-writer]

如果您正在为RTI Connext DDSMicro生成代码,则选项如下:

rtiddsgen [-help]

[-create <typefiles| examplefiles|makefiles>]

[-convertToIdl | -convertToXML]

[-D <name>[=<value>]]

[-d <outdir>]

[-enableEscapeChar]

[-example]

[-exampleTemplate]

[-I <directory>]

[[-inputIdl] <IDLInputFile.idl> | [-inputXml] <XMLInputFile.xml>]

[-language <C|C++>]

[-micro]

[-namespace]

[-ppDisable]

[-ppPath <path to preprocessor>]

[-ppOption <option>]

[-reader]

[-replace]

[-showTemplates]

[-sequenceSize <unbounded sequences size>]

[-strict]

[-stringSize <unbounded strings size>]

[-U <name>]

[-update <typefiles| examplefiles|makefiles>]

[-V <name< [=<value>]]

[-verbosity [1-3]]

[-version]

[-writer]

注意:在使用代码生成器创建的makefile来编译应用程序之前,请确保${NDDSHOME}环境变量的设置如中的设置环境变量(artisetenv)所述RTI Connext DDS入门指南中(RTI Connext DDS GettingStarted Guide.)发布/订阅简介的“动手1”。

表3.1 rtiddsgen选项

选项

描述

-allocateWithMalloc

在C++中使用DDS_Heap_malloc分配可选成员时,使用此标志可获得向后兼容性。

-alwaysUseStdVector

仅适用于指定了-语言C++11的情况。

生成将所有序列映射到std::vector的代码,甚至将映射到rti::core::bounded_sequence的有界序列。

或者,@use_vector注释可以应用于每个序列成员。

-autoGenFiles <architecture>

更新自动生成的文件,即typefile和makefile/项目文件。

要查看每种语言的<体系结构>有效选项,请使用-help选项运行rtiddsgen,或使用字符串

“通用”(-autoGenFiles通用)为所有支持的平台生成兼容的发布者/订户代码。universalarchitecture不会生成makefile/项目文件。

这是以下项的快捷方式:

-更新typefiles-更新makefiles-平台<体系结构>

-constructor

仅当同时指定了-语言C++时适用。

生成类型默认构造函数、复制构造函数、复制赋值运算符和析构函数。使用此选项还将禁用以下TypeSupport方法的生成:create_data(_ex)、delete_

data(_ex)、initialize_data(_e x)、finalize_data。

-create <typefiles| examplefiles|makefiles>

创建指定的文件(typefile、examplefile或makefile)(如果它们不存在)。例如:

rtiddsgen-语言C++11-创建类型文件test.idl如果文件已经存在,则不会修改文件并打印警告。

可以有多个创建选项。

如果为同一文件类型同时指定-create和-update,则只应用-update。

如果使用-create makefile,则需要-platform<arch>选项。例如:

rtiddsgen-语言c-创建makefile-平台x64Darwin17clang9.0 test.idl

-convertToIdl

将输入类型描述文件转换为IDL格式。此选项将创建一个与输入文件同名且扩展名为.idl的新文件。

-convertToXML

将输入类型描述文件转换为XML格式。此选项创建一个与输入文件同名且扩展名为.xml的新文件。

-convertToXsd

将输入类型描述文件转换为XSD格式。此选项将创建一个与输入文件同名且扩展名为.xsd的新文件。

-D <name>[=<value>]

定义预处理器宏。

在Windows系统上,将参数括在引号中:

-D“<name>[=<value>]”

-d <outdir>

在指定目录中生成输出。默认情况下,代码生成器将在找到输入类型定义文件的目录中生成文件。

-disableXSDValidation

导致代码生成器不检查输入XSD文件的格式是否正确。

通常不建议使用此选项,因为代码生成器可能会收到无效输入。

-dllExportMacroSuffix <suffix>

定义在生成Windows DLL时用于导出符号的宏的后缀。默认宏为NDDS_USER_DLL_EXPORT。指定此选项时,宏的名称为NDDS_USER_DLL_

EXPORT_<后缀>。

3 生成示例代码

大多数Connext DDS入门指南(如RTI Connext DDS《入门指南》或RTI Connxt DDS核心库《嵌入式系统入门指南附录》)都要求您创建一个简单的“HelloWorld”应用程序来入门。例如,在macOS上:

$rtiddsgen -language c++11 -example x64Darwin17clang9.0 hello_world.idl

注意:在使用代码生成器Code Generator创建的makefile来编译应用程序之前,请确保按照RTI Connext DDS入门指南中发布/订阅简介的“Hands On 1”中的设置环境变量(artisetenv)中所述设置了${NDDSHOME}环境变量。

熟悉简单的HelloWorld示例后,可以通过指定“高级”模板选项来创建更高级的示例。高级模板已包含在代码生成器中(请参见-exampleTemplate和-showTemplates)。例如,在macOS上:

rtiddsgen -language C+11 -example x64Darwin17clang9.0 -exampleTemplate advanced hello_ world.idl

代码生成器生成的简单示例和高级示例之间有一些主要区别。

注意:Android不支持高级生成的示例™ 或INTEGRITY®平台。

3.1 is_default_qos(true vs. false)

ConnextDDS从当前工作目录中名为USER_QOS_PROFILES.xml的文件加载QoS配置文件。(Connext DDS也可以在其他位置查找此文件;请参阅RTI Connext DDS核心库用户手册中的“如何加载XML指定的QoS设置”)。

简单示例在USER_QOS_PROFILES.xml文件中设置is_default_qos=true。它创建DDS实体而不指定配置文件,因此使用USER_QOS_PROFILES.xml中的默认值。

高级示例还从USER_QoS_PROFILES.xml文件加载QoS。但是,高级示例将is_default_qos设置为false,因此XML没有提供默认值。该示例明确指定了在创建DDS实体时要从XML文件中使用的QoS配置文件。

设置is_default_qos=true是快速入门的一种方便方法,但在生产应用程序中,您应该明确指定要使用的qos配置文件,而不是依赖默认值。请参阅RTI Connext DDS入门指南中的基本QoS一章。

3.2 侦听器Listeners与等待集WaitSets

简单和高级示例都使用WaitSets来阻塞线程,直到数据可用。这是获取数据的最安全的方法,因为它不会影响任何中间件线程(它会阻塞应用程序的主线程,直到数据可用)。

此外,该高级示例在DataReader和DataWriter上安装侦听器,并提供回调,您可以实现这些回调以实现所需的行为。这些侦听器回调是针对各种事件触发的,例如发现匹配的DataWriter或DataReader。侦听器回调是从中间件线程回调的,您不应该阻止它。使用监听器进行非数据回调有好处,因为您不会错过事件。但是,如果在侦听器中阻止或执行缓慢的处理,则可能会导致不希望的行为,例如数据丢失。请参阅RTI Connext DDS核心库用户手册中的侦听器一章。

4 产生文件

下表显示了代码生成器为名为Hello.IDL的示例IDL文件创建的文件。

  • 表5.1 C、传统C++、C++/CLI、为示例“Hello.idl”创建的旧C#文件

  • 表5.2为示例“Hello.idl”创建的现代C++文件

  • 表5.3为示例“Hello.idl”创建的C#文件

  • 表5.4为示例“Hello.idl”创建的Java文件

  • 表5.5为示例“Hello.idl”创建的Ada文件

表5.1 C、传统C++、C++/CLI、为示例创建的旧C#文件“Hello.idl”

产生文件

描述

用户数据类型需要以下文件。源文件应编译并与应用程序链接。需要头文件才能在源中使用数据类型。

除非您打算自定义生成的支持您类型的代码,否则不应修改这些文件。

Hello.[c, cxx, cpp]

HelloSupport.[c, cxx, cpp]

HelloPlugin.[c, cxx, cpp]

为数据类型生成的代码。这些文件包含数据类型的实现。

Hello.h

HelloSupport.h

HelloPlugin.h

包含数据类型实现中使用的声明的头文件。

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用这些文件作为创建发布或订阅用户数据类型的简单应用程序的方法。

application.h (traditional C++ only)

Hello_publisher.cxxand Hello_subscriber.cxxapplications的帮助程序代码

Hello_publisher.[c, cxx, cpp, cs]

发布用户数据类型的应用程序的示例代码。此示例显示了创建发送数据所需的所有DDS对象的基本步骤。

您需要修改代码以设置和更改数据结构中发送的值。否则,只需编译并运行。

Hello_subscriber.[c, cxx, cpp,cs]

订阅用户数据类型的应用程序的示例代码。此示例显示了创建接收数据所需的所有DDS对象的基本步骤。

不需要修改此文件。它已准备好供您编译和运行。

Hello-<architecture>.sln

Hello_publisher-<architecture>.v[c, cs, cx]proj

Hello_subscriber-<architecture>.v[c, cs, cx]-proj

Microsoft Visual Studio解决方案和项目文件,仅为基于Visual Studio的体系结构生成。(示例<architecture>isarmv8Linux4gcc7.3.0。)要编译生成的源代码,请打开工作区文件并构建两个项目。

makefile_Hello_<architecture>

非基于Visual Studio的架构的Makefile。一个<体系结构>的例子是rmv8Linux4gcc7.3.0。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量(QoS)配置从该文件加载。

表5.2为示例“Hello.idl”创建的现代C++文件

产生文件

描述

用户数据类型需要以下文件。源文件应编译并与应用程序链接。需要头文件才能在源中使用数据类型。

除非您打算自定义生成的支持您类型的代码,否则不应修改这些文件。

Hello.cxx

HelloPlugin.cxx

为数据类型生成的代码。这些文件包含数据类型的实现。

Hello.hpp

HelloPlugin.hpp

包含数据类型实现中使用的声明的头文件

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用这些文件作为创建发布或订阅用户数据类型的简单应用程序的方法。

application.hpp

Hello_publisher.cxxand Hello_subscriber.cxxapplications的帮助程序代码

Hello_publisher.cxx

发布用户数据类型的应用程序的示例代码。此示例显示了创建发送数据所需的所有DDS对象的基本步骤。

您需要修改代码以设置和更改数据结构中发送的值。否则,只需编译并运行。

Hello_subscriber.cxx

订阅用户数据类型的应用程序的示例代码。此示例显示了创建接收数据所需的所有DDS对象的基本步骤。

不需要修改此文件。它已准备好供您编译和运行。

Hello-<architecture>.sln

Hello_publisher-<architecture>.vcxproj

Hello_subscriber-<architecture>.vcxproj

Microsoft Visual Studio解决方案和项目文件,仅为基于Visual Studio的体系结构生成。(示例<architecture>isarmv8Linux4gcc7.3.0。)要编译生成的源代码,请打开工作区文件并构建两个项目。

makefile_Hello_<architecture>

非基于Visual Studio的架构的Makefile。一个<体系结构>的例子是rmv8Linux4gcc7.3.0。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量(QoS)配置从该文件加载。

表5.3为示例“Hello.idl”创建的C#文件

产生文件

描述

用户数据类型需要以下文件。源文件应与.NET项目一起编译。

您不应修改这些文件。

Hello.cs

HelloPlugin.cs

为数据类型生成的代码。这些文件包含数据类型的实现。

使用-example<platform>命令行选项(其中<platform>

是.NET平台标识符,如net5或netcoreapp3.1)。您可以修改并使用这些文件来创建发布或订阅用户数据类型的简单应用程序。

HelloProgram.cs

运行HelloPublisher.cs和HelloSubscriber.cs应用程序的代码

HelloPublisher.cs

发布用户数据类型的应用程序的示例代码。此示例显示了创建发送数据所需的所有DDS对象的基本步骤。

您需要修改代码以设置和更改数据结构中发送的值。否则,只需编译并运行。

HelloSubscriber.cs

订阅用户数据类型的应用程序的示例代码。

此示例显示了创建接收数据所需的所有DDS对象的基本步骤。

不需要修改此文件。它已准备好供您编译和运行。

Hello.csproj

NuGet.Config

用于构建和运行应用程序。NuGet.Config告诉.NET编译器在哪里可以找到Rti.ConnextDds NuGet包。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量(QoS)配置从该文件加载。

表5.4为示例“Hello.idl”创建的Java文件

类型

产生文件

描述

由于Java语言要求为每个类创建单独的文件,所以Code Generator将为每个IDL构造生成一个源文件,并将其转换为Java中的类。

常量

Hello.java

与常量关联的类

枚举

Hello.java

与枚举类型关联的类

结构/活接头

Hello.java

HelloSeq.java

HelloDataReader.java

HelloDataWriter.java

HelloTypeSupport.java

结构/联合类序列类DDS DataReader和DataWriter类支持(序列化、反序列化等)类

序列数组的类型定义

Hello.java

HelloSeq.java

HelloTypeSupport.java

包装类序列类支持(序列化、反序列化等)类

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用这些文件作为创建发布或订阅用户数据类型的简单应用程序的方法。

最后一个结构/联合

HelloPublisher.java HelloSubscriber.java

发布或订阅用户数据类型的应用程序的示例代码。您应该修改发布应用程序中的代码,以设置和更改发布数据的值。否则,两个文件都应该准备好编译和运行。

makefile_Hello_

<architecture>

非基于Windows的体系结构的Makefile。一个<体系结构>的例子是rmv8Linux4gcc7.3.0。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量(QoS)配置从该文件加载。

结构/活接头/

类型定义/枚举

HelloTypeCode.java

与IDL类型关联的类型代码类,Hello

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量(QoS)配置从该文件加载。

表5.5为示例“Hello.idl”创建的Ada文件

产生文件

描述

Hello[.h,.c]

为数据类型生成的代码,其中包含数据类型的实现,以及包含数据类型实现中使用的声明的头文件。

HelloSupport[.h,.c]

HelloPlugin[.h,.c]

hello_idl_file[.adb, .ads]

hello_idl_file-hello_datawriter.ads

DataReader和DataWriter类以及序列化/反序列化方法。

hello_idl_file-hello_datawriter.ads

hello_idl_file-hello_typesupport[.adb,.ads]

hello_idl_file-hello_metptypesupport[.adb,.ads]

这些文件仅为支持零拷贝传输共享内存的类型生成(即,在IDL文件中用@transfer_mode(SHMEM_REF)注释)。

hello_idl_file-hello_publisher[.adb,.ads](在示例/目录中)

发布用户数据类型的应用程序的示例代码。您需要修改代码以设置和更改数据结构中发送的值。否则,只需编译并运行。subscriberlistener文件实现了on_data_available()回调。

hello_idl_file-hello_subscriber[.adb,.ads](在示例/目录中)

hello_idl_file-hello_subscriberlistener[.adb,.ads](在示例/目录中)

hello.gpr

使用类似Ada语法的项目文件。这些文件定义了应用程序的构建相关特性。这些特征包括源列表、这些源的位置、生成的对象文件的位置、主程序的名称以及构建过程中涉及的各种工具的选项。每个文件都是一组不同的文件(hello示例用于示例,hello_c用于c文件,hello用于其余ada文件)

hello_c.gpr

hello-samples.gpr (in the samples directory)

使用-example<architecture>命令行选项时会生成以下可选文件。您可以修改并使用此文件来创建发布或订阅用户数据类型的简单应用程序。

USER_QOS_PROFILES.xml

生成的示例中DDS实体的服务质量(QoS)配置从该文件加载。

5 自定义生成的代码

代码生成器允许您通过更改提供的模板,为不同的语言自定义生成的代码。此版本不允许您创建新的输出文件。

可以在现有模板中使用以下命令加载新模板,其中<pathToTemplate>是具有自定义模板的文件夹的绝对路径:

#parse(“<pathToTemplate>/template.vm”)

如果template.vm文件包含宏,则可以在原始模板中使用它。如果template.vm仅包含纯文本而没有宏,则该文本将直接包含在原始文件中。

您可以使用代码生成器提供的预定义变量集自定义模板的行为。有关详细信息,请参阅RTI_rtiddsgen_template_variables.xlsx中的表。

此文件包含两个不同的工作表:语言模板Language-Templates和模板变量Template variables。语言模板工作表显示了所使用的Velocity模板与为每种语言生成的文件之间的对应关系。例如,如果我们想在Hello.C文件中添加一个C语言的方法,我们需要修改templates/C目录下的模板类型Body.vm。

模板的范围可以是:

  • 类型type:如果我们为IDL文件中的每种类型生成一个带有该模板的文件。例如,在Java中,我们为IDL中的每个类型生成一个TypeSupport文件。

  • file:如果我们为每个IDL文件生成一个带有该模板的文件。例如,在C中,我们生成一个包含所有类型插件信息的插件文件。

  • lastTopLevelType:如果我们使用IDL文件中最后一个顶级类型的模板生成一个文件。这通常用于发布者/订阅者示例。

  • 模块:如果我们为IDL文件中的每个模块生成一个带有该模板的文件。这在Ada中使用,其中有包含模块所有类型的文件。

  • topLevelType:如果我们为idl文件中的每个类型生成一个具有该模板的文件。这在ADA中使用,其中发布者/订阅者文件仅为顶级类型生成

该表还显示了可用于该模板的top_level变量。这些变量在工作表模板变量中进行了说明。例如,在Java中,变量的主要单位是constructMap,它是表示类型的变量的hashMap。在C语言中,我们将constructMapList作为主要单元,它是constructMap的列表。在模板变量表中,我们可以看到每个constructMap中包含哪些变量,它适用于的constructKind或类型,以及它包含的值,具体取决于我们使用的语言。

包含类型的constructMap的一个重要变量是memberFieldMapList。此列表表示类型中包含的成员。每个成员也表示为hashMap,其变量也在模板变量表中描述。

除此之外,还有一些环境或常规变量与在名为envMap的hashMap中定义的类型无关。

让我们看一个例子如何使用这些变量。假设我们要在C中生成一个方法,该方法打印结构的成员,如果是数组或序列,则打印相应的大小。对于此IDL:

module Mymodule{

struct MyStruct{

int32 longMember;

int32 arrayMember [2][100];

sequence<char,2> sequenceMember;

sequence <int32, 5> arrayOfSequenceMember[28];

};

};

我们希望生成以下内容:

void MyModule_MyStruct_specialPrint(){

printf(" longMember \n");

printf(" arrayMember is an array [2, 100] \n ");

printf(" sequenceMember is a sequence <2> \n");

printf(" arrayOfSequenceMember is an array [28] is a sequence <5> ");

}

模板中的代码如下所示:

## We go through all the list of types

#foreach ($node in $constructMapList)

##We only want the method for structs

#*--*##if ($node.constructKind.equals(“¡ãstruct”¡À))

void ${node. nativeFQName}_specialPrint(){

##We go through all the members and call to the macros that check if they are array or

sequences

#*----*##foreach($member in $node.memberFieldMapList)

print("$member.name #isAnArray($member) #isASeq($member) \n");

#*----*##end

}

#*--*##end

#end

isAnArray宏检查成员是否为数组(即,具有变量dimensionList),在这种情况下,打印它:

#macro (isAnArray $member)

#if($member.dimensionList) is an array $member.dimensionList #end

#end

isASeq宏检查成员是否为序列(即,具有变量seqSize),在这种情况下,打印它:

#macro (isASeq $member)

#if($member.seqSize) is a sequence <$member.seqSize> #end

#end

启动代码生成器时,可以使用-V<name<[=<value>]命令行选项将新变量添加到模板中。此变量将添加到userVarList hashMap中。您可以在模板中将其称为$userVarList.name或$userVarList.name.equals(value)。

有关速度模板的详细信息,请参见https://velocity.apache.org/engine/1.5/user-guide.html.

6 优化代码生成过程

序列化serialization和反序列化deserialization操作的成本,随着类型复杂性typecomplexity和样本大小sample size的增加而增加。它可以成为发送和接收样本所需的延迟的重要因素。

代码生成器Code Generator提供了命令行选项-optimization,可用于指示序列化serialize/反序列化deserialize操作的优化级别level of optimization。此命令行选项允许选择三个不同级别中的一个。

6.1 优化级别

  • 0:无优化

  • 1:rtiddsgen为typedef生成额外代码,但优化了其使用。如果使用的类型是可以解析为基元、枚举或聚合类型(结构struct、联合union或值类型)的typedef,则生成的代码将调用可以解析typedef的最基本类型的代码。如果不希望修改为typedef生成的代码,则可以使用此级别。

这是Java、C#和C++/CLI语言支持的唯一优化级别。

例如:

typedef int32 Latitude;

typedef int32 Longitude;

struct Position {

Latitude x;

Longitude y;

};

对于优化0,Position类型的样本的序列化将需要调用Latitude和Longitude的序列化方法。例如:

LatitudePlugin_serialize(...) {

serialize_long(...)

}

LongitudePlugin_serialize(...) {

serialize_long(...)

}

Position_serialize(...) {

LatitudePlugin_serialize(...)

LongitudePlugin_serialize(...)

}

通过优化1,rtiddsgen将纬度Latitude和经度Longitude解析为最原始的类型,以实现序列化,从而实现更高效的序列化。在这种情况下,rtiddsgen将保存两个函数/方法调用。

Position_serialize(...) {

serialize_long(...)

serialize_long(...)

}

  • 2: 如果未指定,则此优化级别为默认值。(您也可以明确指定。)此优化级别仅适用于C、C++、C++11、microC、microC++和Ada语言。使用此优化级别,rtiddsgen通过使用更积极的技术来优化结构struct和值类型的序列化/反序列化。这些技术包括嵌套类型nested types的内联扩展,以及当内存布局(C,C++结构布局)与连线布局(XCDR)相同时,使用单个复制函数调用(memcpy)对一组连续成员进行序列化serialization/反序列化deserialization。

6.2 如何应用优化

在代码生成器中,优化(嵌套类型的内联扩展和具有单个副本的连续成员的序列化)是相关的。嵌套结构的内联扩展仅在具有结构标准封装的C/C++内存布局与XCDR布局匹配时进行。(在这种情况下,可以使用单个memcpy对结构的成员进行序列化。)如果具有结构的标准封装的C/C++内存布局与XCDR布局匹配,则rtiddsgen将首先尝试进行内联扩展,然后使用单个副本对连续成员进行串行化serialization。

6.2.1 嵌套类型nested types的内联扩展

内联扩展是一种优化,其中代码生成器将一个类型定义替换为另一个嵌套类型被展平的类型定义。这样做是为了在序列化serialization/反序列化deserialization期间删除额外的函数调用。例如:

struct Point {

int32 x;

int32 y;

};

struct Dimension {

int32 height;

int32 width;

};

struct Rectangle {

Point leftTop;

Dimension size;

};

对于优化级别2,代码生成器将矩形的定义替换为以下等效定义:

struct Rectangle {

int32 leftTop_x;

int32 leftTop_y;

int32 size_height;

int32 size_width;

};

此优化仅用于序列化/反序列化。C/C++中生成的类型继续使用点和维度。

6.2.2 使用单个副本序列化连续成员

在前面的矩形示例中,代码生成器使用优化级别2,通过使用单个复制single copy操作(memcpy)而不是四个来序列化矩形样本,进一步优化了序列化和反序列化。

  • 优化前:

Rectangle_serialize(...) {

memcpy(..., 4) // leftTop_x

memcpy(..., 4) // leftTop_y

memcpy(..., 4) // size_height

memcpy(..., 4) // size_width

}

  • 优化后:

Rectangle_serialize(...) {

memcpy(..., 16) // leftTop_x

}

此优化仅在C/C++结构的内存布局与串行化布局等效时适用,后者使用XCDR版本1或版本2格式。

6.2.3 内联扩展规则

要实现内联,结构“MyStruct”必须满足以下两个要求:

  • 它必须具有C/C++友好的XCDR布局。

  • “MyStruct”的任何成员都不应标记为@min、@max或@range注释。

当满足以下所有条件时,结构/值类型“MyStruct”具有C/C++友好的XCDR布局:

  • 当数据表示为XCDR版本1时,MyStruct标记为@final或@appendable。可变结构不可内联。

  • MyStruct没有基类型。

  • MyStruct仅包含基本成员,或仅由基本成员组成的复杂成员。基元成员是具有以下任意类型的成员:int8,uint8、int16、int32、int64、uint16、uint32、uint64、浮点、双精度、八位字节和字符。内联不支持以下基元类型:long double、wchar、boolean、enum。

struct Dimension {

int32 height;

int32 width;

}; // Inlinable

struct Dimension {

string label; // Inlinable structures cannot contain strings

int32 height;

int32 width;

}; // Not Inlinable

  • 如果任何初始对齐方式(1、2、4、8)大于结构的第一个成员的对齐方式,则属于MyStruct的成员之间没有填充。要应用此规则,请考虑图元类型的这些对齐方式和大小:

表7.1图元类型的对齐和尺寸

基本类型

对齐方式(字节)

大小(字节)

int8

1

1

uint8

1

1

int16

2

2

uint16

2

2

int32

4

4

uint32

4

4

int64

8

8

int64

8

8

float

4

4

double

8

8

octet

1

1

char

1

1

struct Dimension {

int32 height;

int16 width;

}; // Inlinable. Independently of the alignment of the starting memory address (4 or 8),

there is no padding between height and width

struct Dimension {

int16 height;

int32 width;

}; // Not Inlinable. Starting in a memory address aligned to 4 will require adding a

padding of two bytes between height and width

  • 如果任何初始对齐方式(1、2、4、8)大于结构的第一个成员的对齐方式,则MyStruct数组的元素之间没有填充。

struct Dimension {

int32 height;

int16 width;

}; // Not inlinable. Let's assume an array of two dimensions Dimension[2]. If the array

starts in a memory address aligned to 4, there would be padding between the first and the

second element of the array

struct Dimension {

int32 height;

int16 width;

int16 padding;

}; // Inlinable

出于序列化和反序列化的目的,代码生成器将把可内联结构(根据前面的规则)视为基元数组,其中基元类型的对齐方式对应于结构的第一个成员的对齐方式。类型为“MyStruct”的成员将使用单个副本(memcpy)调用进行序列化。

当代码生成器序列化数据结构的成员时,如果可能,它还将尝试将连续基元成员的序列化合并为单个复制操作。代码生成器仅在下一个成员的对齐等于或小于当前成员的对齐时应用此优化。

struct Dimension {

int16 height;

int32 width;

}; // Coalescing not possible because the alignment of width 4 is greater than the alignment of height 2

struct Dimension {

int32 width;

int16 height;

}; // Coalescing is possible because the alignment of width 4 is greater than the alignment of height 2

6.2.4 指南

根据经验,要利用仅包含基本类型的类型的优化级别2:

  • 按降序排列成员(这将有助于复制合并)。

  • 对于XCDR版本2封装,如果您的类型不会演变,请使用@final扩展性。对于XCDR版本1封装,如果可能,请使用@final或@appendable(这将有助于内联扩展)。

  • 如果使用ContentFilteredTopics,建议将筛选器表达式中出现的字段放在类型的开头。

7 提升性能

如果需要使用不同的参数和/或类型文件多次调用代码生成器Code Generator,则每次调用代码生成器时,加载Java虚拟机(JVM)和编译速度模板都会导致性能损失。如果是这样的场景,可以在服务器模式server mode下运行代码生成器Code Generator,以避免多次执行此过程。或者,如果您希望减少JVM启动和执行时间,请使用代码生成器Code Generator提供的JVM优化机制,以减少代码生成时间。

这两个选项(服务器模式server mode和JVM优化)不能一起使用。

7.1 使用服务器模式server mode

提高性能的一种方法是,在服务器模式server mode下运行代码生成器Code Generator。服务器模式运行本机可执行文件,该可执行文件打开与代码生成器的服务器实例的TCP连接,该代码生成器在第一次运行可执行文件时生成,如下所示:

要在服务器模式servermode下调用代码生成器,请使用脚本rtiddsgen_server(.bat),该脚本位于scripts目录中。

CodeGenerator服务器连接到的默认端口是14662。如果要修改Code Generator服务器连接到的端口,请使用-n_serverport<port>参数。请注意,代码生成器服务器最多可以使用三个端口;确保在指定端口之后有两个可用端口(如14663和14664)。

代码生成器服务器提供了一个日志到文件选项,您可以使用参数-n_logfilepath<log directory>来启用该选项。在指定的日志目录中,代码生成器服务器将创建一个名为CodegenServerLog<portNumber>.txt的文件,其中包含来自服务器端的所有日志消息。

代码生成器服务器带有内置超时builtintimeouts,其中一些超时可以更改:

  • 当代码生成器在服务器模式server mode下使用时,JVM在服务器启动时加载一次;速度模板也是一次性编译的。服务器将等待最多5秒以初始化代码生成器。您可以通过使用参数-n_connectiontimeout<timein millises>指定毫秒数来更改此值。

  • 如果代码生成器服务器Code Generator server在一定时间内未被使用(即,如果它没有收到任何呼叫),则它将自动停止。默认值为20秒;您可以通过编辑rtiddsgen_server脚本并调整参数-nservertimeout的值来更改这一点。

  • 代码生成器服务器Code Generator server在接受连接后向客户端发送握手handshake消息。在客户端中,等待握手消息时会超时。如果客户端在短时间内(10秒,一个无法更改的内部值)未收到此消息,则代码生成器客户端将超时。此超时可能意味着端口中正在运行另一个应用程序。

注意:

  • 不支持混合不同版本的代码生成器服务器Code Generator server。请参阅RTI代码生成器发行说明中的限制。

  • 代码生成器服务器Code Generator server无法并行化。代码生成器服务器的每次执行都连接到接收请求的端口,并且每次只能为一个请求生成代码。所以,若您尝试同时发送多个请求,代码生成器服务器将按顺序处理它们。

7.2 使用JVM优化

Java虚拟机(JVM)提供了不同的选项,有助于提高其性能。RTI在创建代码生成器JVM时应用了其中的一些选项,从而提高了代码生成器Code Generator的执行时间。由于这些选项是非标准的,因此默认情况下将禁用它们。如果您使用的是Connext DDS附带的JRE,则可以启用这些选项;否则,启用这些选项的风险自负。

应用于代码生成器JVM的选项如下:

-XX:+TieredCompilation

-XX:TieredStopAtLevel=1

-XX:CICompilerCount=4

-Xverify:none

-XX:+UseParallelGC

-XX:+OptimizeStringConcat

-XX:CompileThreshold=5000

有关这些选项的更多信息,请参阅JDK文档:

https://docs.oracle.com/en/java/javase/11/ 。(目前,您可以在“创建和构建应用程序的主要工具Main Tools to Create and Build Applications”>“java”中找到“工具参考”中描述的大多数选项)。

若要启用与代码生成器JVM选项相关的性能改进,请将RTIDDSGEN_JVM_OPTIONIC环境变量设置为true。要禁用改进,请取消设置环境变量。(默认情况下,未设置。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/192109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新来一个卷王,天天加班到12点,太让人崩溃......

在程序员职场上&#xff0c;什么样的人最让人反感呢&#xff1f; 是技术不好的人吗&#xff1f;并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗&#xff1f;也不是。技术很强的同事&#xff0c;可遇不可求&#xff0c;向他学习还来不及呢。 真正让人反…

2023全网汇总PMP备考攻略(附答题技巧资料)

一&#xff0c;多复习和学习新版考纲 01《PMBOK》看三遍 这边建议看三遍《PMBOK》&#xff0c;更有利于我们巩固知识&#xff0c;查缺补漏。 第一遍 第一遍是老师带着我们去看。这个时候一定要非常专心&#xff0c;千万不要上课走神或者玩手机。因为这一遍老师会告诉我们&a…

结构型设计模式 Structural Patterns :适配器 Adapter(C++ 实现)

文章大纲 适配器简介对象适配器类适配器C++ 实现代码参考文献与学习路径Structural PatternsAdapterMatch interfaces of different classesBridgeSeparates an object’s interface from its implementationCompositeA tree structure of simple and composite objectsDecorat…

C#中的那些警告如何去除?完全去除C#警告

一般在c中没有使用的变量会有警告&#xff0c;C#中也有&#xff0c;在QT中我们利用Q_UNSED可以直接消除这些警告&#xff0c;那么我们在C#中该如何做才能消除这些不必要的警告呢&#xff1f;经过查询微软官方网站发现&#xff0c;有的找到了解决方法&#xff0c;有的仍然一筹莫…

学习bootstrap怎么样?

想必学习前端的都知道这个响应式框架&#xff0c;之前我接触这个框架的时候是在学习前段页面设计的进阶教程是接触的&#xff0c;那个时候要做那种登陆注册界面&#xff0c;里面的输入框很让人头疼有时候电脑的宽度不一样或者是写了一个精美的网页然后放到手机上的时候就变了模…

【C++】继承(基类和派生类的关系、菱形虚拟继承、继承和组合)

文章目录1、继承的概念和定义2、基类和派生类的赋值转换3、继承中的作用域4、派生类的默认成员函数5、继承与友元和静态成员6、复杂的菱形继承及菱形虚拟继承7、继承和组合1、继承的概念和定义 继承是面向对象程序设计上程序复用的重要手段&#xff0c;以往接触的复用都是函数复…

程序员的自律之路

世界的精彩不是单纯的美丽&#xff0c;毕竟丑恶也是美丽的食粮&#xff0c;黑暗也是光明的救世主 很久没有写博客了&#xff0c;最近半年不太稳定&#xff0c;也经历了一些自我成长的东西。 事后我进行深度反省&#xff0c;思考一个人或者说是一个程序员的失控原因到底是什么&a…

推荐几款好用的企业级文档管理软件

知识库&#xff0c;又称为智能数据库或人工智能数据库。知识库的概念来自两个不同的领域&#xff0c;一个是人工智能及其分支-知识工程领域&#xff0c;另一个是传统的数据库领域。由人工智能&#xff08;AI&#xff09;和数据库&#xff08;DB&#xff09;两项计算机技术的有机…

Java字符串查找(3种方法)

在给定的字符串中查找字符或字符串是比较常见的操作。字符串查找分为两种形式&#xff1a;一种是在字符串中获取匹配字符&#xff08;串&#xff09;的索引值&#xff0c;另一种是在字符串中获取指定索引位置的字符。根据字符查找String 类的 indexOf() 方法和 lastlndexOf() 方…

金融公司在 2022 年扩大了对下一代技术的投资

根据 Broadridge Financial Solutions, Inc. 的一份新报告&#xff0c;大多数金融服务公司现在认为数字化转型对其业务至关重要&#xff0c;并且已经在寻求下一波技术来帮助取得成功。 在对 500 名最高管理层高管及其在全球买方和卖方的直接下属进行的 2023 年数字化转型和下…

代码随想录算法训练营第五十七天_第九章_动态规划 | 1143.最长公共子序列、1035.不相交的线、53. 最大子数组和 动态规划

LeetCode 1143.最长公共子序列 视频讲解https://www.bilibili.com/video/BV1ye4y1L7CQ文章讲解https://programmercarl.com/1143.%E6%9C%80%E9%95%BF%E5%85%AC%E5%85%B1%E5%AD%90%E5%BA%8F%E5%88%97.html 思路&#xff1a;代码&#xff1a;LeetCode 1035.不相交的线 视频讲解h…

技术开发119

技术开发119 业务内容&#xff1a; 汽车零部件的制造产业用机械零部件的设计、制造、组装电机零部件的制造 公司简介&#xff1a; 董事长&#xff1a;管原胜安 资本金&#xff1a;3200万日元 员工数&#xff1a;36名 成立时间&#xff1a;1972年7月 资格认证&#xff1a…

【学习笔记】coursera | Computational Neuroscience | Week 1

Course Introduction 1.1 Course Introduction 三种模型 Descriptive models of the brain&#xff08;描述型, what&#xff09;&#xff1a;神经元如何对外部刺激做出反应&#xff1f;用神经元编码模型如何量化描述&#xff1f;如何从神经元中获取信息&#xff08;解码&am…

Linux 中 su 命令的使用

目录 &#x1f34d;①普通用户切换 root 用户 &#x1f349;②root 用户切换普通用户 su 命令的作用是在 Linux 中切换用户&#xff0c;是英文单词&#xff1a;Switch&#xff08;切换&#xff09; User&#xff08;用户&#xff09; 的缩写。 语法&#xff1a; su [-] 用户…

三维引擎大盘点

近年&#xff0c;智慧城市、数字孪生大热&#xff0c;三维引擎就成为了绕不过去的一个词&#xff0c;但是目前市场的的三维引擎多的让人头晕目眩&#xff0c;他们各自都有哪些优缺点呢&#xff0c;今天我们就来盘点下主流的三维引擎。 常见的三维引擎按平台可分为客户端三维引擎…

1613_PC汇编语言_位操作

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 这一次看一下位操作的章节。 如果是逻辑位操作其实不需要考虑大小端。 1. 移位操作在快速乘除法中经常用到。 2. 这里提到了一个算是移位&#xff0c;其实跟前面的…

Hive(4):场景案例:Apache Hive初体验

1 体验1&#xff1a;Hive使用起来和Mysql差不多吗&#xff1f; 1.1 背景 对于初次接触Apache Hive的人来说&#xff0c;最大的疑惑就是&#xff1a;Hive从数据模型看起来和关系型数据库mysql等好像。包括Hive SQL也是一种类SQL语言。那么实际使用起来如何&#xff1f; 1.2 过…

激光投影仪哪款好?坚果N1 Pro和海信Vidda C1和当贝X3测评

当贝x3、坚果N1Pro和海信Vidda C1都是近期比较热门的激光投影仪,作为消费者来说选择哪一款比较好呢?看看实测对比和参数对比就知道它们的区别了。(一)三款激光投影仪的实测对比1)外观对比:坚果N1 Pro枪灰加深灰的色彩组合,自带了一个云台,能够支持任意角度调整,但比普通的投影…

【6s965-fall2022】量化 Quantization Ⅰ

模型的大小不仅和参数量的多少有关&#xff0c;而且也和位宽有关。 ModelSize#ParameterBitWidth.ModelSize \#Parameter BitWidth. ModelSize#ParameterBitWidth. 低位宽的运算操作容易实现、运算速度快、功耗低。 什么是量化&#xff1f; 从广义上讲&#xff0c;量化是将连…

龙蜥开发者说:6 年前打开的开源“潘多拉盲盒”,如今都解了哪些未知数 | 第 15 期

「龙蜥开发者说」第 15 期来了&#xff01;开发者与开源社区相辅相成&#xff0c;相互成就&#xff0c;这些个人在龙蜥社区的使用心得、实践总结和技术成长经历都是宝贵的&#xff0c;我们希望在这里让更多人看见技术的力量。本期故事&#xff0c;我们邀请了龙蜥社区开发者陈成…