Documentation

    Table of Content
    • CodePorting.Native Product Family
      • CodePorting.Native Cs2Cpp
        • Getting Started
          • Product Overview
          • Installation
          • Licensing
          • How to use CodePorting.Native Cs2Cpp
            • How to Use Command line to port and build Projects
            • How to Use GUI to port and build Projects
        • Developer Guide
          • Porting Simple C# Projects
            • Porting Simple Console Application
            • Porting Simple Library
            • Porting Simple NUnit Test
          • Porting Dependent C# Projects
            • Porting Dependent Console Application
            • Porting Dependent Library
            • Porting Dependent NUnit Test
          • Porting Complex C# Projects
            • How to Convert Complex C# Console Application to C++
            • How to Convert Complex C# Library to C++
            • How to Convert Complex C# NUnit Test to C++
          • What Converts to What
            • Abstract Classes
            • Auto Properties
            • Break Statements
            • Class Constructors
            • Continue Statements
            • Delegates
            • Do While Statemetns
            • Enums TypeCast
            • Enums
            • Events
            • Exceptions
            • Expected Exceptions
            • Finalizers
            • For Statements
            • ForEach Statements
            • Generic Classes
            • Generic Delegates
            • Generic Interfaces
            • Generic Methods
            • Generic Structs
            • If Statements
            • Indexers
            • Lambda Expressions
            • Methods
            • Nested Classes
            • Properties
            • Return Statements
            • Simple Class
            • Simple Interface
            • Simple Struct
            • Simple Test
            • Standard TypeCast
            • Static Class
            • Static Constructor
            • Static-Methods
            • Static Properties
            • Switch Statements
            • Test with Setup Methods
            • Throw Statements
            • Try Catch Finally Statements
            • Try Catch Statements
            • Try Finally Statements
            • Var Expressions
            • Virtual Methods
            • While Statements
          • CodePorting Native Cs2Cpp Attributes
          • CodePorting Native Cs2Cpp Configuration File
            • CodePorting.Native Cs2Cpp Configuration File Structure
            • Attributes in Configuration file
            • Configuration file Nodes
            • Configuration file Options
          • Memory Management Model
            • Using aliasing constructor to create a smart pointer
          • Cmake Support
          • Limitations and Bugs
            • Porter Limitations and Bugs
            • Library Limitations and Bugs
            • Cpp Code Injection
        • Release Notes
          • 2021
            • CodePorting.Native Cs2Cpp 21.4
            • CodePorting.Native Cs2Cpp 21.3
            • CodePorting.Native Cs2Cpp 21.2
            • CodePorting.Native Cs2Cpp 21.1
          • 2020
            • CodePorting.Native Cs2Cpp 20.12
            • CodePorting.Native Cs2Cpp 20.11
            • CodePorting.Native Cs2Cpp 20.10
            • CodePorting.Native Cs2Cpp 20.9
            • CodePorting.Native Cs2Cpp 20.8
            • CodePorting.Native Cs2Cpp 20.7
            • CodePorting.Native Cs2Cpp 20.6
            • CodePorting.Native Cs2Cpp 20.5
            • CodePorting.Native Cs2Cpp 20.4
            • CodePorting.Native Cs2Cpp 20.3
            • CodePorting.Native Cs2Cpp 20.2
            • CodePorting.Native Cs2Cpp 20.1
          • 2019
            • CodePorting.Native Cs2Cpp 19.1
            • CodePorting.Native Cs2Cpp 19.2
            • CodePorting.Native Cs2Cpp 19.3
            • CodePorting.Native Cs2Cpp 19.4
            • CodePorting.Native Cs2Cpp 19.4.1
            • CodePorting.Native Cs2Cpp 19.5
            • CodePorting.Native Cs2Cpp 19.6
            • CodePorting.Native Cs2Cpp 19.7
            • CodePorting.Native Cs2Cpp 19.8
            • CodePorting.Native Cs2Cpp 19.9
            • CodePorting.Native Cs2Cpp 19.10
            • CodePorting.Native Cs2Cpp 19.11
            • CodePorting.Native Cs2Cpp 19.12
          • 2018
            • CodePorting.Native Cs2Cpp 18.9
            • CodePorting.Native Cs2Cpp 18.9.1
            • CodePorting.Native Cs2Cpp 18.10
            • CodePorting.Native Cs2Cpp 18.11
            • CodePorting.Native Cs2Cpp 18.12
    1. Home
    2. CodePorting.Native Product Family
    3. CodePorting.Native Cs2Cpp
    4. Developer Guide
    5. Porting Complex C# Projects
    6. How to Convert Complex C# Console Application to C++

    How to Convert Complex C# Console Application to C++

    What's on this Page

      • Porting Complex Console Application
        • Porting BaseLibrary
        • Porting CommonLibrary
        • Porting LibraryA
        • Porting LibraryB
        • Porting ComplexConsoleApp

     

    Note that this example is built upon several assumptions, namely:
    • Porter is installed to //C:\//CodePorting.Native_Cs2Cpp//_19.4// directory
    • All C# projects are located in //C:\ComplexConsoleApp// directory
    • The output directory for all projects is //C:\output//

    Porting Complex Console Application

    This example demonstrates how to port five C# projects, one being a Console Application C# project and another four are interdependent library projects on which the Console Application project depends. We’ll use pre-existing projects from ComplexConsoleApp example located here.

    This example consists of five C# projects – BaseLibrary, CommonLibrary, LibraryA, LibraryB and ComplexConsoleApp. We’ll port projects one by one starting from the least dependent one.

    Porting BaseLibrary

    BaseLibrary is a library project consisting of a single .cs source file //IBaseInterface.cs// and a project file //BaseLibrary.csproj//. This project does not have any special dependencies on other projects or 3rd party assemblies.

    Also BaseLibrary project directory contains pre-created configuration file //BaseLibrary.porter.config//. Let us have a closer look at it.

    BaseLibrary.porter.config is quite simple. It begins with an XML declaration, which specifies that the file contains an XML document.
    
    Then goes the XML root element <porter> which is mandatory for Porter configuration XML document
    
        <porter>
    
    Next, the default Porter configuration file is imported using <import> element. The default configuration assigns default values to all configuration options.
    
        <import config="porter.config"/>
    
    And the XML document is finished with closing tag of the root element <porter>:
    
        </porter>

    This example assumes that C# BaseLibrary library project should be ported into C++ static library project, which is a default setting.

    With C# project at hand and configuration file ready, we can start porting the project.

    In order to covert BaseLibrary project we run CMD and navigate to the directory with porter binary:

    >cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
    

    And run Porter:

     >CsToCppPorter.exe -c C:\ComplexNUnitTest\BaseLibrary\BaseLibrary.porter.config C:\ComplexNUnitTest\BaseLibrary\BaseLibrary.csproj C:\output
    

    Porter will print some logs of the porting process to the console window and when it finishes porting, directory //C:\output// will contain a directory named //BaseLibrary.Cpp// containing the generated C++ source files and Cmake configuration files.

    Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the //C:\output\BaseLibrary.Cpp// directory

     >cd C:\output\BaseLibrary.Cpp
    

    And run Cmake in configuration mode:

     >Cmake --G "Visual Studio 15 2017"
    

    And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:

     >Cmake --build . --config Release
    

    The library is built.

    Porting CommonLibrary

    The second project in this example is located in //CommonLibrary// directory. CommonLibrary is a library project consisting of a single .cs source file //BaseInterfaceSimplImpl.cs// and a project file //CommonLibrary.csproj//. This project has a dependency on BaseLibrary project. This dependency has to be reflected in CommonLibrary project’s configuration file. In our example this configuration file is pre-created, its name is //CommonLibrary.porter.config// and it is located in the project’s directory //CommonLibrary//. Let us have a closer look at the configuration file.

    CommonLibrary.porter.config begins with an XML declaration, which specifies that the file contains an XML document  
    
    
    
    Then goes the XML root element <porter> which is mandatory for Porter configuration XML document
    
        <porter>
    
    Next, the default Porter configuration file is imported using <import> element. The default configuration will assign default values to all configuration options
    
        <import config="porter.config"/>
    
    Also we need to import a configuration file include_map.config from ported BaseLibrary project that maps public types exported by CommonLibrary library to generated C++ header files in which these types are declared. include_map.config is generated by Porter for each project it ports. Thus, before porting CommonLibrary library project, BaseLibrary project has to be ported first so that Porter generates include_map.config. This is how include_map.config is included in CommonLibrary.porter.config:
    
        <import config="../../output/BaseLibrary.Cpp/include_map.config" />
    
    Here ../../output is a directory that was passed as an output directory to Porter when BaseLibrary project was ported.
    
    This example assumes that C# project CommonLibrary should be ported into C++ shared/dynamic library project, therefore we assign value ‘true’ to make_shared_lib option:
    
        <opt name="make_shared_lib" value="true" export_per_member="true"/>
    
    Next, we want Porter to add some commands to the output CMakeLists.txt file. We do that by adding <cmake_commands> element to the configuration file containing raw Cmake commands
    
        <cmake_commands>
           <![CDATA[
    
    The following commands set the output directory for the library’s binary by setting the corresponding properties on the target ${PROJECT_NAME}:
    
          set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY   "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
          set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
    
    Here ${PROJECT_NAME} is the name of the Cmake project which is equal to the name of the main Cmake executable target.
    
    Because on “DLL-platforms” (i.e. Windows) a DLL shared library is considered by Cmake an executable entity and on “non-DLL-platforms” (i.e. Linux) a shared object is considered by Cmake a library, we set both RUNTIME_OUTPUT_DIRECTORY and LIBRARY_OUTPUT_DIRECTORY properties.
    
    Then the <cmake_commands> element is closed:
    
          ]]>    
        </cmake_commands>
    
    And last but not least, we need to tell Porter that CommonLibrary project depends on BaseLibrary library. We do it using <lib> element:
    
        <lib csname="BaseLibrary">
          <cmake_link_template>
            <![CDATA[
              find_package(BaseLibrary.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../BaseLibrary.Cpp" NO_DEFAULT_PATH)
              target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE BaseLibrary.Cpp)
            ]]>
           </cmake_link_template>
        </lib>
    
    Here ${PROJECT_NAME}_dependencies is the name of the Cmake Interface Library target that is defined in the output CMakeLists.txt and is linked to main executable target ${PROJECT_NAME}. Thus libraries linked to ${PROJECT_NAME}_dependencies get automatically linked to ${PROJECT_NAME} target.
    
    Finally the XML document is finished with closing tag of the root element <porter>:
    
        </porter>

    With the C# project at hand and configuration file ready, we can convert the project.

    In order to covert CommonLibrary project we run CMD and navigate to the directory with porter binary:

    >cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
    

    And run Porter:

    >CsToCppPorter.exe -c C:\ComplexNUnitTest\CommonLibrary\CommonLibrary.porter.config C:\ComplexNUnitTest\CommonLibrary\CommonLibrary.csproj C:\output
    

    Porter will print some logs of the porting process to the console window and when it finishes porting, directory //C:\output// will contain a directory named //CommonLibrary.Cpp// containing the generated C++ source files and Cmake configuration files.

    Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the //C:\output\CommonLibrary.Cpp// directory

    >cd C:\output\CommonLibrary.Cpp
    

    And run Cmake in configuration mode:

    >Cmake --G "Visual Studio 15 2017"
    

    And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:

    >Cmake --build . --config Release
    

    When build finishes, directory D:\output\bin\Release should contain a .dll file //CommonLibrary.Cpp.dll.// which has just been built from C++ sources.

    Porting LibraryA

    The third project in this example is located in LibraryA directory. LibraryA is a library project consisting of a single .cs source file //ClassAImpl.cs// and a project file //LibraryA.csproj//. This project has a dependency on two previously ported projects BaseLibrary and CommonLibrary. These dependencies have to be reflected in LibraryA project’s configuration file. In our example this configuration file is pre-created, its name is //LibraryA.porter.config// and it is located in the project’s directory //LibraryA//. Let’s have a closer look at this file.

    LibraryA.porter.config begins with an XML declaration, which specifies that the file contains an XML document
    
    Then goes the XML root element <porter> which is mandatory for Porter configuration XML document
    
        <porter>
    
    Next, the default Porter configuration file is imported using <import> element. The default configuration will assign default values to all configuration options  
    
        <import config="porter.config"/>
    
    Because LibraryA has dependency on BaseLibrary and CommonLibrary projects, we need to import configuration files include_map.config from both ported projects. This is how include_map.config files are included in LibraryA.porter.config:
    
        <import config="../../output/BaseLibrary.Cpp/include_map.config" />
        <import config="../../output/CommonLibrary.Cpp/include_map.config" />
    
    Here ../../output is a directory that was passed as an output directory to Porter when BaseLibrary and CommonLibrary projects were ported.
    
    And last but not least, we need to tell Porter that LibraryA project depends on BaseLibrary and CommonLibrary library. We do it using <lib> element  
    
        <lib name="CommonLibrary.Cpp" csname="CommonLibrary">
           <cmake_link_template>
             <![CDATA[
               find_package(CommonLibrary.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../CommonLibrary.Cpp" NO_DEFAULT_PATH)
               target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE CommonLibrary.Cpp)
             ]]>
          </cmake_link_template>
        </lib>
        <lib csname="BaseLibrary">
           <cmake_link_template>
             <![CDATA[
               find_package(BaseLibrary.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../BaseLibrary.Cpp" NO_DEFAULT_PATH)
               target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE BaseLibrary.Cpp)
             ]]>
          </cmake_link_template>
        </lib>
    
    Finally the XML document is finished with closing tag of the root element <porter>:
    
        </porter>

    With C# project at hand and configuration file ready, we can convert the project.

    In order to covert LibraryA project we run CMD and navigate to the directory with porter binary:

    >cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
    

    And run Porter:

    >CsToCppPorter.exe -c C:\ComplexNUnitTest\LibraryA\LibraryA.porter.config C:\ComplexNUnitTest\LibraryA\LibraryA.csproj C:\output
    

    Porter will print some logs of the porting process to the console window and when it finishes porting, directory //C:\output// will contain a directory named //LibraryA.Cpp// containing the generated C++ source files and Cmake configuration files.

    Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the //C:\output\LibraryA.Cpp// directory

    >cd C:\output\LibraryA.Cpp
    

    And run Cmake in configuration mode:

    >Cmake --G "Visual Studio 15 2017"
    

    And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:

    >Cmake --build . --config Release
    

    The library is built.

    Porting LibraryB

    The fourth project in this example is located in LibraryB directory. LibraryB is a library project consisting of a single .cs source file //ClassBImpl.cs// and a project file //LibraryB.csproj//. This project has a dependency on two previously ported projects BaseLibrary and CommonLibrary. These dependencies have to be reflected in LibraryB project’s configuration file. In our example this configuration file is pre-created, its name is //LibraryB.porter.config// and it is located in the project’s directory //LibraryB//. Let us have a closer look at LibraryB’s configuration file.

    LibraryB’s configuration file is much the same as LibraryA’s one described above. One difference is that because this example assumes that LibraryB should be built into a shared dynamic library, this has to be explicitly stated in the configuration file
    
        <opt name="make_shared_lib" value="true" export_per_member="true"/>
    
    And another difference is that we want to set the output directory for the library binary file just like we did it in ComomnLibary’s configuration file described above
    
        <cmake_commands>
          <![CDATA[
            set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
            set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
          ]]>
        </cmake_commands>

    With C# project at hand and configuration file ready, we can convert the project.

    In order to covert LibraryA project we run CMD and navigate to the directory with porter binary:

    >cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
    

    And run Porter:

    >CsToCppPorter.exe -c C:\ComplexNUnitTest\LibraryB\LibraryB.porter.config C:\ComplexNUnitTest\LibraryB\LibraryB.csproj C:\output
    

    Porter will print some logs of the porting process to the console window and when it finishes porting, directory //C:\output// will contain a directory named //LibraryB.Cpp// containing the generated C++ source files and Cmake configuration files.

    Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the //C:\output\LibraryB.Cpp// directory

    >cd C:\output\LibraryB.Cpp
    

    And run Cmake in configuration mode:

    >Cmake --G "Visual Studio 15 2017"
    

    And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:

    >Cmake --build . --config Release
    

    When build finishes, directory D:\output\bin\Release should contain just built .dll file //LibraryB.Cpp.dll// along with previously built //CommonLibrary.Cpp.dll//.

    Porting ComplexConsoleApp

    The last project in this example is located in //ComplexConsoleApp// directory. ComplexConsoleApp is an executable project that consists of a single .cs source file //Program.cs// and a project file //ComplexConsoleApp.csproj//. This project has a dependency on all four previously ported projects – BaseLibrary, CommonLibrary, LibraryA and LibraryB. These dependencies have to be reflected in the ComplexConsoleApp project’s configuration file. In our example this configuration file is pre-created, its name is //ComplexConsoleApp.porter.config// and it is located in the project’s directory //ComplexConsoleApp//. Let us have a closer look at the configuration file.

    ComplexConsoleApp.porter.config begins with an XML declaration, which specifies that the file contains an XML document
    
    Then goes the XML root element <porter> which is mandatory for Porter configuration XML document
    
        <porter>
    
    Next, the default Porter configuration file is imported using <import> element. The default configuration will assign default values to all configuration options
    
        <import config="porter.config"/>
    
    Also we import include_map.config files from all four previously ported library projects
    
        <import config="../../output/LibraryA.Cpp/include_map.config" />
        <import config="../../output/LibraryB.Cpp/include_map.config" />
        <import config="../../output/BaseLibrary.Cpp/include_map.config" />
        <import config="../../output/CommonLibrary.Cpp/include_map.config" />
    
    Next, we want Porter to add some commands to the output CMakeLists.txt. We do that by adding <cmake_commands> element to the configuration file containing raw Cmake commands
    
         <cmake_commands>
          <![CDATA[   
    
    The first command sets the output directory for the executable binary by setting the corresponding property on the target ${PROJECT_NAME}
    
        set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../bin")
    
    Here ${PROJECT_NAME} is the name of the Cmake project which is equal to the name of the main Cmake executable target.
    
    Then the <cmake_commands> element is closed
          ]]>
         </cmake_commands>
    
    Then, we need to tell Porter that ComplexConsoleApp project depends on four libraries. We do it using <lib> element:
    
        <lib name="BaseLibrary.Cpp" csname="BaseLibrary">
          <cmake_link_template>
            <![CDATA[
              find_package(BaseLibrary.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../BaseLibrary.Cpp" NO_DEFAULT_PATH)
              target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE BaseLibrary.Cpp)
            ]]>
         </cmake_link_template>
        </lib>
    
        <lib name="CommonLibrary.Cpp" csname="CommonLibrary">
           <cmake_link_template>
             <![CDATA[
               find_package(CommonLibrary.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../CommonLibrary.Cpp" NO_DEFAULT_PATH)
               target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE CommonLibrary.Cpp)
             ]]>
          </cmake_link_template>
        </lib>
    
        <lib name="LibraryA.Cpp" csname="LibraryA">
          <cmake_link_template>
            <![CDATA[
              find_package(LibraryA.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../LibraryA.Cpp" NO_DEFAULT_PATH)
              target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE LibraryA.Cpp)           
            ]]>
          </cmake_link_template>
        </lib>
    
        <lib name="LibraryB.Cpp" csname="LibraryB">
           <cmake_link_template>
            <![CDATA[
              find_package(LibraryB.Cpp REQUIRED CONFIG PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../LibraryB.Cpp" NO_DEFAULT_PATH)
              target_link_libraries(${PROJECT_NAME}_dependencies INTERFACE LibraryB.Cpp)
            ]]>
          </cmake_link_template>
        </lib>
    
    Here ${PROJECT_NAME}_dependencies is the name of the Cmake Interface Library target that is defined in the output CMakeLists.txt file and is linked to main executable target ${PROJECT_NAME}. Thus libraries linked to ${PROJECT_NAME}_dependencies get automatically linked to ${PROJECT_NAME} target.
    
    Finally the XML document is finished with closing tag of the root element <porter>
    
    </porter>

    With the C# project at hand and configuration file ready, we can convert the project.

    In order to covert ComplexConsoleApp project we run CMD and navigate to the directory with porter binary:

    >cd C:\CodePorting.Native_Cs2Cpp_19.4\bin\porter
    

    And run Porter:

    >CsToCppPorter.exe -c C:\ComplexConsoleApp\ComplexConsoleApp\ComplexConsoleApp.porter.config C:\ComplexConsoleApp\ComplexConsoleApp\ComplexConsoleApp.csproj C:\output
    

    Porter will print some logs of the porting process to the console window and when it finishes porting, directory //C:\output// will contain a directory named //ComplexConsoleApp.Cpp// containing the generated C++ source files and Cmake configuration files.

    Now we want to use Cmake to generate makefile/project files. Let it be a Visual Studio 2017 x86 project file. In CMD we navigate to the //C:\output\ComplexConsoleApp.Cpp// directory

    >cd C:\output\ComplexConsoleApp.Cpp
    

    And run Cmake in configuration mode:

    >Cmake --G "Visual Studio 15 2017"
    

    And now we can build the sources using either Cmake or Visual Studio. Let us use Cmake:

    >Cmake --build . --config Release
    

    When build finishes, directory D:\output\bin\Release should contain four files: CommonLibrary.dll, LibraryB.dll, ComplexConsoleApp.Cpp.exe, which has just been built from sources, and aspose_cpp_vc140.dll, which was copied from Porter installation directory during a post-build step. When we run ComplexConsoleApp.Cpp.exe its output to the Console window should be similar to the output of the original C# application project we ported.