AnyOption Class, An Example of C# Wrapper Class of Native C++ Class

I have been blogging about the great amazing features of C# .NET PInvoke Interop SDK Tool, I have also shown the power of the C# .NET Library for the Standard C++ Library. It is time for me to present how easily and quickly a C# wrapper class for a native C++ class can be generated automatically in just a few seconds, you will be able to see how a native C++ class can be wrapped in a C# class instantly and gets integrated with .NET seamlessly, calling C++ class method from C# .NET can never be easier. If you are a developer like me who always wants to write code efficiently and productively using both C# and native C++, you would find the solution of bridging the native C++ and C# .NET can save you so much time of using native C++ DLL.

The class I picked for demonstration is AnyOption, you can find the C++ implementation at GitHub. I am not going to post the code here, you can take a look at the C++ source code there. AnyOption is a C++ class for easy parsing of complex command line options. It was written for Unix platform, but I was able to build the class into a windows native C++ DLL very quickly in less than a minute. Once I opened the C++ DLL from NGenerator, all the exported methods except the private methods were being shown in the following screen shot.

As you can see, all the public and protected functions of AnyOption class are being shown in the screen shot. Simply by looking at the prototypes of the functions, you will find that most of the function parameter types are not complicated, they are int, char, char const *(same as const char *), char **. There are configuration setting you can use to marshal the data type by default, for example, char const* will be marshaled as string by default, char * will be marshaled as StringBuilder by default, char ** will be marshaled as a string array. You can still use the type marshaling designer to change the marshaling for specific method. You do not need to change the type marshaling for the primitive C++ data type since there is only one marshaling for them in the C# world. In the solution explorer, you can choose to show only the functions with possible multiple type marshaling as shown below.

There are still too many of them which I don’t necessary do anything to them because I am happy with marshaling char const * to string, that is exactly what it represents in the native C++ DLL. Then I choose to show the function with possible multiple type marshaling without default type marshaling. After filtering all the functions with default type marshaling, the functions I will need to fine tune by using the type marshaling designer came down to 3 as shown below,

If you have read the source code of the C++ AnyOption class, you know that the type of char** in all three functions is string array, and its preceding parameter of an integer type of these 3 functions is the length of the string array. By using the type marshaling designer, this char ** type can be easily marshaled as string array without writing single line of code, I was able to do it in less than a minute.

The resulting implementation of the C# method looks like it was written by us, developers. Actually, we had iterated all the possible scenario of all the data types NGenerator supports in C++, so the code below was actually the code we usually writes to marshal the C++ data type in C#.

I also presented the source code of the other two methods implemented in C#.

After building the C# wrapper project, a .NET assembly containing the single AnyOption class was created, here is the meta data of the C++ class I copied from Visual Studio.

It has same neat interface as in the native C++ class. NGenerator allows you to remove the beginning underscore of a parameter name, so you don’t see any parameter starting with ‘_’ in the C# wrapper class.

With the help of C# .NET PInvoke Interop SDK, integrating any C++ native DLL is so easy and quick, you simply grab the native C++ DLL and the header files then feed them to NGenerator, you will get a C# .NET assembly which is ready for use in your C# application right away. Best of all, the maintenance if quite easy as well, all the custom type marshaling is saved, If you change the native C++ DLL and the change still applies to the C++ class function whose interface does not change, the only thing you need to do is to fine tune the newly added function and modified function which does require fine tuning, otherwise you will just need to re-generate the wrapper project and rebuild it.

In the near future, I will continue to demonstrate wrapping more complicated native C++ DLL in C# .NET.

 

Translate »