[Top][All Lists]
[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