dotgnu-general
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [DotGNU]Overriding C++ virtual methods in C#


From: Adam Treat
Subject: Re: [DotGNU]Overriding C++ virtual methods in C#
Date: Fri, 6 Dec 2002 14:20:13 -0500
User-agent: KMail/1.4.7

On Friday 06 December 2002 01:17 pm, Gopal V wrote:
> So I create QWidgetBridge and QObjectBridge to wrap these ... so here
> QWidgetBridge inherits from QObjectBridge to inherit bridging (which
> seems to be the obvious plan here, correct me if I'm wrong).

No, QWidgetBridge will inherit from QWidget, but *not* QObjectBridge.

> So the inheritance pattern looks like this
>
> QObject
>
>  |     \__ QObjectBridge
>
> QWidget         |
>        \__ QWidgetBridge
>
> (which is the Multiple Inheritance diamond drawn in ASCII art :-)
>
> Since QWidgetBridge should inherit QObjectBridge *and* QWidget to be
> useful for the purpose ....

Here is the inheritance tree:

QObject

  |     \__ QObjectBridge

QWidget
        \__ QWidgetBridge

> Now if I call QWidgetBridge.vmethod() which one will get called ?,
> the options are
>
> 1) QWidget::vmethod           (inherited via QWidget)
> 2) QObjectBridge::vmethod     (inherited via QWidgetBridge)
>
> Since QWidgetBridge does not override vmethod, we really cannot be sure.
>
> (DISCLAIMER: I don't know if there's a way in C++ to avoid this)

Here is the amended version of marcus example to extend to more inheritance:

//Compile widget.cpp with
//        g++ -shared -o libwidget.so widget.cpp

#include <iostream>

class Widget
{
        public:
        
        virtual void virtualMethod1()
        {
                std::cout << "Widget::virtualMethod1() [the REAL built-in 
method]"
                        << std::endl;
        }
        
        virtual void virtualMethod2()
        {
                std::cout << "Widget::virtualMethod2() [the REAL built-in 
method" << std::endl;
        }
        
        virtual void doSomething()
        {
                std::cout << "Widget::doSomething calling virtualMethod1()" << 
std::endl;
                virtualMethod1();
                std::cout << "Widget::doSomething calling virtualMethod2()" << 
std::endl;
                virtualMethod2();
        }
};

class SubWidget: public Widget
{
        public:
        
        void virtualMethod1()
        {
                std::cout << "SubWidget::virtualMethod1() [the REAL built-in 
method]"
                        << std::endl;
        }
        
        void virtualMethod2()
        {
                std::cout << "SubWidget::virtualMethod2() [the REAL built-in 
method" << std::endl;
        }
        
        void doSomething()
        {
                std::cout << "SubWidget::doSomething calling virtualMethod1()" 
<< std::endl;
                virtualMethod1();
                std::cout << "SubWidget::doSomething calling virtualMethod2()" 
<< std::endl;
                virtualMethod2();
        }
};

class WidgetBridge: public Widget
{
        public:
        
        void* (*virtualMethod1_Callback)();
        void* (*virtualMethod2_Callback)();
        
        void virtualMethod1()
        {
                virtualMethod1_Callback();
        }
        
        void virtualMethod2()
        {
                virtualMethod2_Callback();
        }
};

class SubWidgetBridge: public SubWidget
{
        public:
        
        void* (*virtualMethod1_Callback)();
        void* (*virtualMethod2_Callback)();
        
        void virtualMethod1()
        {
                virtualMethod1_Callback();
        }
        
        void virtualMethod2()
        {
                virtualMethod2_Callback();
        }
};

extern "C"
{

Widget* new_WidgetBridge(
        void* (*vm1_callback)(),
        void* (*vm2_callback)() )
{
        WidgetBridge* w = new WidgetBridge();
        w->virtualMethod1_Callback = vm1_callback;
        w->virtualMethod2_Callback = vm2_callback;
        return (Widget*) w;
}

void WidgetBridge_doSomething( Widget* instPointer )
{
        ((WidgetBridge*) instPointer)->doSomething();
}

void Widget_virtualMethod1( Widget* instPointer )
{
        instPointer->Widget::virtualMethod1();
}

void Widget_virtualMethod2( Widget* instPointer )
{
        instPointer->Widget::virtualMethod2();
}

SubWidget* new_SubWidgetBridge(
        void* (*vm1_callback)(),
        void* (*vm2_callback)() )
{
        SubWidgetBridge* w = new SubWidgetBridge();
        w->virtualMethod1_Callback = vm1_callback;
        w->virtualMethod2_Callback = vm2_callback;
        return (SubWidget*) w;
}

void SubWidgetBridge_doSomething( SubWidget* instPointer )
{
        ((SubWidgetBridge*) instPointer)->doSomething();
}

void SubWidget_virtualMethod1( SubWidget* instPointer )
{
        instPointer->SubWidget::virtualMethod1();
}

void SubWidget_virtualMethod2( SubWidget* instPointer )
{
        instPointer->SubWidget::virtualMethod2();
}

} // extern "C"

//widget.cs
using System;
using System.Runtime.InteropServices;


public class Widget
{
        IntPtr rawObject;
        
        public delegate void virtualMethod1Delegate();
        public delegate void virtualMethod2Delegate();
        virtualMethod1Delegate vm1Delegate;
        virtualMethod2Delegate vm2Delegate;
        
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern IntPtr new_WidgetBridge(
                [MarshalAs(UnmanagedType.FunctionPtr)] virtualMethod1Delegate 
d1,
                [MarshalAs(UnmanagedType.FunctionPtr)] virtualMethod2Delegate 
d2
                 );
        
                 
        public Widget()
        {
                vm1Delegate = new virtualMethod1Delegate( VirtualMethod1 );
                vm2Delegate = new virtualMethod2Delegate( VirtualMethod2 );
                rawObject = new_WidgetBridge( vm1Delegate, vm2Delegate );
        }
        
        internal Widget(QtNull dummy) {}
        
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern void Widget_virtualMethod1(IntPtr instPointer);
        public virtual void VirtualMethod1()
        {
                Widget_virtualMethod1(rawObject);
        }
        
                
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern void Widget_virtualMethod2(IntPtr instPointer);
        public virtual void VirtualMethod2()
        {
                Widget_virtualMethod2(rawObject);
        }
        
        
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern void WidgetBridge_doSomething(IntPtr 
instPointer);
        public virtual void DoSomething()
        {
                WidgetBridge_doSomething(rawObject);
        }
}

public class SubWidget: Widget
{
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern IntPtr new_SubWidgetBridge(
                [MarshalAs(UnmanagedType.FunctionPtr)] virtualMethod1Delegate 
d1,
                [MarshalAs(UnmanagedType.FunctionPtr)] virtualMethod2Delegate 
d2
                 );
                 
        public SubWidget(): base(QtNull.Instance)
        {
                vm1Delegate = new virtualMethod1Delegate( VirtualMethod1 );
                vm2Delegate = new virtualMethod2Delegate( VirtualMethod2 );
                rawObject = new_SubWidgetBridge( vm1Delegate, vm2Delegate );
        }
        
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern void SubWidget_virtualMethod1(IntPtr 
instPointer);
        public override void VirtualMethod1()
        {
                SubWidget_virtualMethod1(rawObject);
        }
        
                
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern void SubWidget_virtualMethod2(IntPtr 
instPointer);
        public override void VirtualMethod2()
        {
                SubWidget_virtualMethod2(rawObject);
        }
        
        
        [DllImport("libwidget", CharSet=CharSet.Ansi)]
        private static extern void SubWidgetBridge_doSomething(IntPtr 
instPointer);
        public override void DoSomething()
        {
                SubWidgetBridge_doSomething(rawObject);
        }
}

internal struct QtNull
{
        private static readonly QtNull instance = new QtNull (null);

        private QtNull (Object dummy) {}

        internal static QtNull Instance {
                get {return instance;}
        }
}

public class CustomWidget1: Widget
{
        public CustomWidget1(): base() {}
        
        public override void VirtualMethod2()
        {
                Console.WriteLine("C# version of Widget.VirtualMethod2");
        }
}

public class CustomWidget2: SubWidget
{
        public CustomWidget2(): base() {}
        
        public override void VirtualMethod2()
        {
                Console.WriteLine("C# version of SubWidget.VirtualMethod2");
        }
}

public class Testing
{
        public static void Main()
        {
                Widget w1 = new CustomWidget1();
                Widget w2 = new CustomWidget2();
                w1.DoSomething();
                y2.DoSomething();
                Environment.Exit(0);
        }
}

Does this work?

Cheers,

Adam


reply via email to

[Prev in Thread] Current Thread [Next in Thread]