Why use a CLI Wrapper to Call a C# dll from C++
The advantage of the wrapper is that instead of having to build commands to pass the CLI, you can simple use methods and pass the parameters.)
Calling a C# class from native C++ using C++/CLI)
Recently we had the need to write a class to handle the communication between a laser jet printer and Production Floor application written in C++. This new class was to be written in C# so we had to create a ‘wrapper’ to allow communication between the native C++ application and the managed class.
C++/CLI allows for the creation of C++ programs that can use both .NET classes and native C++ types. It has built in support for marshalling between managed and unmanaged types. It this instance we are using it to call a C# method and will then return the result to the C++ application.
In this article I will illustrate the steps needed to set up the communication between a C++ application and a C# class library.
C# Class Library
Below is a simple C# class with a method that accepts two parameters, logs them using nlog and returns a string. The class library project was created using the .NET framework 4.6.2.
C++/CLI Wrapper
As previously mentioned, this is the link between the C# class and the main C++ application. This project was created using the empty CLR Class project in Visual Studio. Once the project is created, a header and source file were added. A reference to C# class library dll was also added to the project.
Header File
A couple of items to note from the header file:
- When a class is declared with dllexport, all its member functions and static data members are exported. This eliminates the need for a module definition (.def) file. If all the definitions for these members are not provided a linker error is generated. For additional information see here.
- The forward declaration of the CSharpWrapperPrivate class is required to let the compiler know that it refers to a class defined elsewhere, in the source file.
Source File
Some items to note from the main source file:
- To be able to convert between native and managed environments a marshalling library can be using. This library consists of a set of functions and a marshal_context class for converting between the common types. This library is defined in the include/msclr directory of Visual Studio. For more information see here.
- h à Functions for marshaling standard C++ types
- the auto_gcroot class is used for automatic resource management.
- gcnew is used for .NET references, and objects created with gcnew will be automatically garbage collected.
- The handle character (^) is equivalent to a * (or pointer) and is used for accessing .NET reference types. It modifies the type specifier to mean that the declared object should be automatically deleted when the object is no longer accessible. For more information see here.
- When sending a string to the C# dll a new System::String is created in the call. This is done to change from the native string type to the managed type.
- When a string is returned from the C# dll is it changed back to the native string using marshal_as<std::string> before returning to the main C++ application. The marshal_as method is used to convert data between native and managed environments.
One additional setting to be changed within the project properties to set the Configuration Type to be a Dynamic Library (dll) instead of Application (.exe).
Main C++ application
In order to use the CLR dll in the main C++ application there are a number of steps required:
- Update the Configuration Properties of the project
- Under VC++ Directories, in the Include Directories value add a reference to the folder containing the CSharpWrapper.h file.
- Under Linker-> Input, add the entry “CSharpWrapper.lib” to Additional Dependencies.
- Copy the necessary dlls into the root folder where the exe will be ran from.
- dll
- dll
- dll & nlog.config (only required for logging purposes in this example).
Once the configuration properties are set up as above then add a reference to the header file in the code as follows
- #include “CSharpWrapper.h”
The following snippet of code can then be used to call the method in the CLI dll
Further Reading / References
Article used as a basis for the projects created in this example can be found here.
Get in Touch
To stay up to date with Dataworks Limited news and events, connect with us via the links below or call us on 051 878 555 today: