How to inherit from a native C++ class in C# and then use the class in native C++?
To answer this question, what we need to do from C# is to achieve the following 3 things,
-
Subclass/inherit C++ classes from C#
-
Override C++ methods with C# methods
-
Expose or pass the instances of C# class to C++ as if they were native code
Just like using C++/CLI, there is simply no way we can override any C++ virtual method directly using C# class by deriving from the native C++ class, we are talking about two different language. What xInterop C++ .NET Bridge can do is to create a wrapper bridge C# class for the underlying native C++ class, and developers can subclass or inherit from the wrapper C# class.
There are multiple scenario that we would want to inherit from the native C++ class. What I can think about is,
1. Some or all of the existing implementation of the virtual methods of the underlying C++ class do not meet our requirements, we would want to override those methods from C#.
2. The native C++ class is an abstract class representing an interface, we will have to implement in C# before we can pass an instance of such interface back to the native C++.
I will be presenting a simple example for us to look into the details of such a scenario that we must implement a so called C++ interface from C#.
// C++ abstract class representing an interface of INotification. class INotification { public: // Always reserve a slot in the virtual function table so that we can make sure any derived class's destructor be called. virtual ~INotification() {}; // A function to notify that a message has arrived. virtual void OnNotify(const char * message) = 0; }; // Initialize the DLL with a pointer to the given C++ abstract class. void Initialize(INotification * notification); // Called to notify with a given message. void Notify(const char * message);
We are only going to export two methods from this native DLL.
LIBRARY LibCallback EXPORTS Initialize @1 Notify @2
The following screenshots show how I was able to create the xInterop C# wrapper project using xInterop C++ .NET Bridge.
Step 1: Choose the type of xInterop project.
Step 2: Create xInterop C++ .NET Bridge project.
Step 3: Set up a new .NET to Native C++ Bridge project.
Step 4: Further configuration of the .NET to Native C++ Bridge project.
Step 5: Add abstract class.
Step 6: How to choose to add a callback class.
Step 7: Add a callback class
Since we want to override the C++ method in C#, we must tell xInterop C++ .NET Bridge to treat the class of INotification callback class. A callback class in C# would allow us to override the virtual methods, in the case that we need to pass an instance of the C++ class, we may pass an appointer of the C# class.
Step 8: Generate the C# wrapper source code.
Step 9: The logging message.
Step 10: The source code structure.
The following virtual method is the one we will need to override in C#. Since an instance of the class of INotification is created from C# without calling the constructor of the native C++ class, there is no virtual function address to be initialize by the native C++ if the class is not sub-classed. The delegate variable is actually null.
public virtual void OnNotify(string message) { try { this.delegateOfINotification_OnNotifyDelegate(this.___ptrObject___, message); GC.KeepAlive(this); } catch(SEHException exception) { // throw an enhanced SEH exception which may contain the error message of orignal C++ exception. throw EnhancedSEHExceptionManager.Create(exception); } }
In order to use the generated C# .NET assembly, we also created a console application named NotificationDemo to demonstrate how to call the C# callback class.
First, we will need to derive from the existing C# wrapper class of INotifiication.
public class Notification : INotification { public Notification() { } public override void OnNotify(string message) { Console.WriteLine(message); } }
Secondly, we will need to create the Program class and Main method to call all the related C# methods to pass the message to the underlying native DLL and gets callback to the Notification class.
using System; using xInterop.Win32.LibCallback; namespace NotificationDemo { class Program { static void Main(string[] args) { // Creates an instance of Notification which derives from the C# bridge class of INotification. Notification notificaiton = new Notification(); // Initialize the underlying native DLL by passing an instance of the Notification class. LibCallbackWrapper.Initialize(notificaiton); // Notify the underlying native DLL with a message. This call will call back to Notification class. LibCallbackWrapper.Notify("This is a C# message passed to native C++ DLL which then gets passed back into C# by using callback class."); } } }
The post Inheriting from native C++ in C# and passing the inherit class backward to c++ appeared first on xInterop C++ .NET Bridge.