How to generate code for a base and derived IDL in separate DLL files
Note: Applies to RTI Connext DDS 5.2.0 and above.
RTI Code Generator has an option called -dllExportMacroSuffix <suffix>
, which allows you to configure the macro suffix used to export type plugin symbols when building a Windows DLL. This feature is particularly useful if you want to place the generated code (from interdependent IDL files) in different DLL libraries.
This article explains how to do this in case one type (derived type) inherits from another type (base type). It also explains how to import the resulting DLL files into a Visual Studio project.
The option -dllExportMacroSuffix
should receive a unique suffix for each IDL file. It will enforce the creation of a .lib file containing all the information about unmanaged symbols exported by each DLL. This option defines the macro suffix that is used to export symbols when building Windows DLLs. The default macro is NDDS_USER_DLL_EXPORT
. When this option is specified, the name of the macro is NDDS_USER_DLL_EXPORT_<suffix>
.
Please note that if you generate the code with the -example
option to rtiddsgen, a Visual Studio DLL project will be created automatically inside the solution. This is very convenient, since the .sln project will already have all the necessary dependencies.
Attached you will find a file called base_and_derived_types.zip. It contains two IDL files: base.idl and derived.idl, which inherits the type from base.idl. The next sections explain how to compile the generated code for derived.idl in C, C++, C# and C++/CLI.
How to compile a derived project in C#
1. Generate code with rtiddsgen for the base type (base.idl):
> "%NDDSHOME%\bin\rtiddsgen" -example <architecture> -language C# -dllExportMacroSuffix BASE base.idl
Compile the generated project. Two files named base_type.lib and base_type.dll will be generated inside the bin\<x64/i86>\<Release/Debug-architecture> subdirectory.
2. Generate code with rtiddsgen for the derived types (derived.idl):
>"%NDDSHOME%\bin\rtiddsgen" -example <architecture> -language C# -dllExportMacroSuffix DERIVED derived.idl
3. In the derived .sln project, add the base_type.lib file to the linker input. You can do this in Visual Studio by right-clicking on the non-C# project, “Properties->Configuration Properties->Linker->Input->Additional dependencies”.
Note: Use an absolute path as "Additional Dependencies" if the path to base_type.lib is not added to ‘Additional Library Directories.' This way, the linker will be able to resolve all unmanaged symbols required by the derived project.
4. Again, in the derived .sln project, add the base_type.dll from your base type as a reference. You can do this by right-clicking on the non-C# project references and then “Add Reference…”. Click on “Browse…” and select the base_type.dll file, then click OK. By doing this, the linker will be able to resolve managed symbols. Now all symbol dependencies should be resolvable.
5. Build your derived project.
How to compile a derived project in C/C++
1. Generate code with rtiddsgen for the base type (base.idl):
> "%NDDSHOME%\bin\rtiddsgen" -example <architecture> -language C++ -dllExportMacroSuffix BASE base.idl
2. Define NDDS_USER_DLL_EXPORT_BASE
in the preprocessor properties of every base project (Configuration Properties->C/C++->Preprocessor->Preprocessor Definitions). This will expose the generated code functions.
Compile the generated project. A file named base_publisher.lib will be generated inside the objs/<architecture> subdirectory.
3. Generate code with rtiddsgen for the derived types (derived.idl):
>"%NDDSHOME%\bin\rtiddsgen" -example <architecture> -language C++ -dllExportMacroSuffix DERIVED derived.idl
4. In the derived DLL project, define NDDS_USER_DLL_EXPORT_DERIVED
. Also include the LIB file from the base type (base_publisher.lib) in the linker input. You can do this in Visual Studio by right-clicking on the DLL project, “Properties->Configuration Properties->Linker->Input->Additional dependencies.”
Note: Use an absolute path as "Additional Dependencies" if the path to base_publisher.lib is not added to the Additional Library Directories. This way, the linker will be able to resolve all unmanaged symbols required by the derived project.
5. Build your derived project.
How to compile a derived project in C++/CLI
1. Generate code with rtiddsgen for base.idl:
> "%NDDSHOME%\bin\rtiddsgen" -example <architecture> -language C++/CLI -dllExportMacroSuffix BASE base.idl
2. A .lib file will be created in the bin\<Release/Debug-architecture> subdirectory when you compile the project from the .sln file. You need to force the creation of a DLL library. In order to do that, you need to make some changes in the base .sln file. Right-click on the publisher or subscriber project and then “Properties->General->Configuration Type” and change “Application (.exe)” to “Dynamic Library (.dll)”. In “Properties->General->Target Extension”, change “.exe” to “.dll”. Then, in “Properties->Linker->General->Output File”, select “<inherit from parent or project defaults>”.
3. Build the project and you will see the .dll file in bin\<x64/i82>\<Release/Debug-architecture>. It should be called “base_<publisher/subscriber>.dll.”
4. Generate code with rtiddsgen for derived.idl:
>"%NDDSHOME%\bin\rtiddsgen" -example <architecture> -language C++/CLI -dllExportMacroSuffix DERIVED derived.idl
5. Open the derived .sln file. Open <publisher/subscriber> properties and then: “Properties->Linker->Input->Additional Dependencies”. In that field, add: “base_<publisher/subscriber>.lib.”
Note: Use an absolute path as "Additional Dependencies" if the path to base_<publisher/subscriber>.lib is not added to the Additional Library Directories. This way, the linker will be able to resolve all unmanaged symbols required by the derived project.
Under the project, right-click on “References” and select “Add reference…”. Click on “Browse…” and select “base_<publisher/subscriber>.dll”, then click OK.
If you want to compile both publisher and subscriber projects, do step #5 for both of them.
6. Compile the derived project.