Quantcast
Channel: xInterop C++ .NET Bridge
Viewing all articles
Browse latest Browse all 31

Inheriting from native C++ in C# and passing the inherit class backward to c++

$
0
0

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.

image

Step 2: Create xInterop C++ .NET Bridge project.

image

Step 3: Set up a new .NET to Native C++ Bridge project.

image

Step 4: Further configuration of the .NET to Native C++ Bridge project.

image

Step 5: Add abstract class.

image

Step 6: How to choose to add a callback class.

image

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.

image

Step 8: Generate the C# wrapper source code.

image

Step 9: The logging message.

image

Step 10: The source code structure.

image

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.


Viewing all articles
Browse latest Browse all 31

Trending Articles