How is nested class in native C++ handled by xInterop NGen++ ?

How is inner class in C++ wrapped in C# by xInterop NGen++?

In C++, an inner class or nested class is a class declared entirely within the body of another class, nesting class. Inner classes are basically a form of scope. C# supports inner class or nested class as well, so mapping a nested C++ class in a nesting C++ class to a nested C# wrapper class in a nesting C# wrapper class is doable in theory. But how?

The following native C++ code is a very simple example of declaring a nested class inside another class, a nesting C++ class. In the following example, the nested native C++ class is called NestedObject which is declared and implemented inside of the nesting C++ native class named SimpleObject.

xInterop NGen++ (A C# wrapper generator for the native C++ DLL) fully supports nested class, nested struct/structure, nested enum, even nested anonymous struct/structure and nested anonymous enum via pure Explicit P/Invoke. Calling into a native nested C++ class from C# .NET and accessing its method and fields has no difference of calling a regular native C++ class.

We always look into the issues which other code generators such as like SWIG (Simplified Wrapper and Interface Generator) and CXXI are facing while working on implementing and improving xInterop NGen++. CXXI is not very active as of today. SWIG does not really support nested classes or its support is limited from reading its document, but it does provide some workarounds with defining the nested class inside the nesting class where it is forward declared, which means the actual declaration and implementation should be defined outside of the class where the nested class is forward declared in order for SWIG to process it. On SWIG’s to-do-list of 2013 Google Summer of Code, the difficulty is marked as medium to hard. I am not an expert of SWIG implementation or using SWIG to create C# wrapper semi-automatically, but I think its difficulty may have something to do with the fact that SWIG’s underlying mechanism of wrapping C++ is another layer of C style DLL, which means SWIG must wrap the native C++ DLL in a C style DLL which then gets wrapped in C# by using Explicit P/Invoke.

When wrapping the native un-managed native C++ class residing in a native C++ DLL, xInterop NGen++ takes a different approach than SWIG. xInterop NGen++ does not try to wrap the original C++ native un-managed DLL in another C style DLL except that it needs to generate a supplement C++ DLL when any instantiated template class is not exported in the original C++ DLL in order to export the instantiated template class, xInterop NGen++ uses the native C++ DLL as it is. The C# .NET code generated by xInterop NGen++ operates on the pointer of C++ object/instance exactly like a traditional C++ application linking with that native C++ DLL based on the information of the memory layout and the method signatures of a C++ object, including both exported methods and virtual methods. The resulting C# wrapper class has exact same interface of the corresponding native C++ class does, which enables developers to easily convert a C++ application to a C# application when using the native C++ DLL via the generated C# wrapper library.

To xInterop NGen++, any native unmanaged C++ object is basically just a pointer pointing to the beginning of a specific block of memory in the unmanaged native world. The layout, virtual function table and the exported methods of the C++ object are all known to xInterop NGen++. An instance of a nested class is just another native pointer. So it does not matter if the class of the object is nested or not. Basically speaking, being nested or not is just a name scope of the class definition in the original C++ source code.

The way which xInterop NGen++ chose to handle the native nested C++ class is same as the way of handling other regular native C++ classes, a corresponding C# .NET wrapper class gets generated for each native nested C++ class. As for the name scope or namespace, the C# .NET wrapper class of the native nested C++ class will be put inside of the C# .NET wrapper class of the C++ nesting class where the native C++ nested class resides so that the original C++ class structure can be maintained.

I have listed the meta data and class definition of the C# .NET wrapper class of the native C++ nesting class along with nested class below.

If you look into the preceding code carefully, you would find that the structure of the interface of the C# nested inner class has no much difference than a regular top-level C# wrapper class, they are both derived from the same base C# class, the only difference is that the nested inner class is declared and implemented in another C# wrapper class like it does in C++. It is a difference on the name scope in C++ native world, it is also just the same difference on the name scope in the C# managed world, so they are perfectly matched in both worlds.

Wrapping the native C++ class with multiple inheritance in C#

Generating C# wrapper class for the native C++ class with multiple inheritance

xInterop NGen++ fully supports wrapping the native C++ class with multiple inheritance by using C# .NET Explicit P/Invoke.

Let’s talk about the concept of C++ multiple inheritance first briefly. In C++, you can derive a class from any number of base classes. Deriving a class from more than one direct base class is called multiple inheritance.

On the other hand, C# unfortunately only supports deriving from a single base class.

Take a look at the following class diagram for example. The following classes are part of SFML implementation with our version of SFML C# Wrapper libraries as I discussed in the previous blog.

In the preceding example, class Window, RenderTarget are direct base classes for the derived class RenderWindow:

We will be able to wrap each class one-to-one in C# for class RenderWindow, class Window and RenderTarget. While in C#, we won’t be able to do the following like in C++ because C# only supports single inheritance.

The solution we use in xInterop NGen++ is to let class RenderWindow derive from the first class, in this case, class Window and then generate code to implement the public methods of all other classes in a way of interface, more clearly, explicit interface, so the implementation of class RenderWindow in C# shall look like the following,

In the C# wrapper library, IRenderTarget defines all the public methods in the wrapper class of RenderTarget. The reason we chose to implement C# explicit interface instead of C# implicit interface is that we want to guarantee that there is no method with the same name and the same signature in class Window and the interface of IRenderTarget since generating C# wrapper code is an automated process.

This does introduce inconvenience because the method implemented in class RenderWindow via explicit interface is private, you will have to type-cast RenderWindow to IRenderTarget before you can access the methods of IRenderTarget.

Generating SFML C# .NET Wrapper Libraries in 10 minutes – Part I

Introduction

“SFML (Simple and Fast Multimedia Library) is a portable and easy-to-use API for multimedia programming. It is an object oriented alternative for the SDL. SFML provides 2D graphics that are hardware accelerated with OpenGL. SFML can also be used for OpenGL windowing. SFML also provides different modules made to ease programming games and multimedia applications. It is written in C++, it does already have a binding for .NET, which is not my concern, what I am caring about is that how I would be able to create the C# wrapper libraries for the whole packages of C++ DLLs automatically using xInterop NGen++. (By the way, this is going to be the official name of the C# .NET PInvoke Interop SDK for the native C++ DLL)

“The modules currently available are:

All the modules can be used independently, except the Graphics module that depends on the Window module, and all the modules that depend on the System module.

By using xInterop NGen++, I was able to build 5 individual C# .NET wrapper assemblies for all the 5 modules in less than 10 minutes. (I certainly spent a few hours testing them to make sure they work correctly with a couple of examples of using SFML, I did not have any knowledge of SFML, I went to its web site to learn all the samples, it was easy though since I just needed to change the syntax from C++ to C#.) Their assembly names and namespaces are automatically given based on the names of the original C++ native DLLs.

NSpeech.Win32.Nsfml_system_2
NSpeech.Win32.Nsfml_audio_2
NSpeech.Win32.Nsfml_network_2
NSpeech.Win32.Nsfml_window_2
NSpeech.Win32.Nsfml_graphics_2

Since I have both x86/win32 32 bits and x64 64 bits DLLs, I was able to build C# .NET Assemblies targeting AnyCPU, which means I will be able to use the DLL under x86, x64 platform or x64 WoW.

By using those C# .NET assemblies, I was able to write the C# example code which looks almost similar to the original C++ sample code since they share the same class names, same methods name inside of each class. All I had to do is to change the syntax of declaring variables and calling methods.

I studied the C++ samples from SFML tutorials here for a few minutes and I picked up one simple sample of creating shapes. The following is the original C++ code to create an outline of a circle shape, which I shamefully copied from SFML web site with credits to Laurent Gomila.

Now, let’s write some C# code to call the SFML C++ code via the C# wrapper libraries generated by xInterop NGen++, remember, the auto-generated C# source code only replies on Explicit P/Invoke, but really, it is so easy and simple to call the C++ class methods or access the C++ internal properties from C# by using the auto-generated C# wrapper classes.

Here is a C# example to create a outline of the shape of a circle.

And here is the draw method which accepts a parameter of the base class of any drawable class, namely Drawable class. This way, I will be able to draw any supported drawable objects in a window.

If you peruse the preceding C# code carefully, you will find renderWindow is an object of RenderWindow, it gets converted to an interface of IRenderTarget. This is because RenderWindow class is derived from both Window class and RenderTarget class, C# does not support multiple inheritances like C++ does, xInterop NGen++ uses an interface of RenderTarget to implement multiple inheritances. We will discuss multiple inheritances implementation in C# for C++ classes in the near future since this is a very important feature for a code generator like xInterop NGen++.

Here is the captured image by running the preceding sample C# code. You can find the similar image created by the original C++ code from here.

This is the Part I. Stay tuned, I will present the Part II soon.

Do you always marshal const char * to string in C# when calling native C++ class from C# ?

Do you always marshal “const char *” to string in C# when calling native C++ class method from C# ?

Most of time, yes, we would simply marshal “const char *” to string in C#/.NET and it just works. but it does not always work as expected from the native C++ DLL because “const char*” can also represent an array of binary data in bytes as read-only array. The reason of my writing this post is that I read a question from here, and I realized how NGen++ is superior than SWIG on generating C# wrapper for native C++ DLLs because SWIG has to reply on complicated macro called typemap. SWIG which is an open source project and it brings the bridge between C++ and all other various languages with huge efforts, but I would say this is exactly the main reason I would not want to use SWIG even before I wrote NGen++, I would want an automated tool which only requires me to do a few minor configuration to generate the C# wrapper class automatically without writing any type of scripts. I guess that is one of the big reasons I have been writing my own C# wrapper generator for native C++ DLL.

When a parameter of “const char*” or “char *” contains binary data, it can also include zero(0) which represents the ending of a C/C++ string, so marshaling const char * or “char*” to a string definitely does not work as expected from the native C++ DLL because the string will get cut in the middle when being passed from C# code to the native C++ class, It must be marshaled to an array of bytes with a length if it is not a fixed-length array.

Since 90+% of the time, “const char*” does represent a string in C++, so NGen++ marshals “const char*” to string by default, but it will also allow developers to marshal “const char*” to an array of byte by using the C++ to C# type marshaling designer. You would probably think that using a type marshaling designer would be as inconvenient as using typemap scripting, but the fact is that you would only need to spend a few seconds to configure the type mapping using the type marshaling designer without any further knowledge of anything else beyond using the C++ to C# type marshaling designer, especially involving writing scripted typemap which would also cause additional errors since it is kind of another type of language, and very often developers would probably introduce new errors.

Here is the C++ implementation of C++ class of Buffer I made up. The function of SetData is what we will be discussing.

By default, the following wrapper method of SetData will be generated by NGen++,

By using the C++ to C# type marshaling designer shown below, I was able to quickly convert the implementation of the wrapper method to an array of bytes.

The implementation of SetData wrapper method will look like exactly as expected from the native C++ class of Buffer as shown below. As you see, the signature of the wrapper method changed, so did the P/Invoke signature. Since array parameter of the wrapper method already has the length of the array, it does not need another parameter to tell the length of the array.

Translate »