View previous topic :: View next topic |
Author |
Message |
simhau
Joined: 06 Feb 2007 Posts: 55
|
Posted: Sun Jan 13, 2008 5:36 pm Post subject: Extending D classes in MiniD |
|
|
Is this actually possible..?
I have a UI for SDL written in D, and I want MiniD to control everything. Now the application just launches a MiniD script and lets MiniD have full control.
But I want to be able to extend my classes so I can override the events, but I get an error when I'm testing this...
MapView.constructor(native): MDValue.to() - Cannot convert 'instance of class MyMapView' to 'WrappedInstance'
Is there some way of achieving this without too much work? |
|
Back to top |
|
|
simhau
Joined: 06 Feb 2007 Posts: 55
|
Posted: Sun Jan 13, 2008 9:51 pm Post subject: |
|
|
I've almost found a workaround for my event problems..
I just need to know how I can manually convert between my D type and the wrapped MiniD type.
I tried using the ToMiniDType from bind.d, but I wasn't allowed...
I bet theres a simple way of doing this, but I couldn't find it in the documentation, and theres quite a lot code to browse. |
|
Back to top |
|
|
JarrettBillingsley
Joined: 20 Jun 2006 Posts: 457 Location: Pennsylvania!
|
Posted: Sun Jan 13, 2008 11:08 pm Post subject: |
|
|
Extending wrapped D classes in MiniD might seem to work in some cases, but there are some serious issues with it. Namely, if you have a class A that you derive from and override a method of in MiniD, when a native function that takes an A calls that overridden method, it won't call the method that was declared in MiniD, it'll call the base class (A's) method. Basically the problem is: what state do you call that overridden method in? The native method isn't passed a state parameter, and it might not even know anything about MiniD at all (like in a lib not written expressly for use with MiniD). Pyd doesn't have any problem with this case because there is only one global interpreter in Python. This is unsolvable without some serious changes in the way the interpreter works and is something I really want to rectify for MiniD 2. |
|
Back to top |
|
|
simhau
Joined: 06 Feb 2007 Posts: 55
|
Posted: Mon Jan 14, 2008 6:23 am Post subject: |
|
|
I see. It would have been really useful, so I hope you are able to sort out those issues for MD2.
As I said, I think I have a workaround for my event handling.
I've added some functions to my widget class that takes an MDClosure as a parameter. This is then added in my event signal class just as delegates and functions is. This will allow me to use MiniD for event handling, but my problem is passing parameters to the MiniD function...
The callbacks is called with two classes, the Widget that raised the event, and an Event class containing data. Both these classes are wrapped in MiniD, but when using MDContext.easyCall() I need to send instances of MDValue.
I don't know how I can convert my native D classes to the wrapped MiniD types.
This is not optimal as I don't want these classes to know about MiniD, but it's more important that I can actually use MiniD with my library |
|
Back to top |
|
|
JarrettBillingsley
Joined: 20 Jun 2006 Posts: 457 Location: Pennsylvania!
|
Posted: Mon Jan 14, 2008 7:18 am Post subject: |
|
|
Go ahead and make the ToDType and ToMiniDType functions public; there was a reason I made them private in the first place but to be honest I can't remember what it was
The binding library is admittedly one of the weaker parts of the library, sorry I haven't worked on it that much. |
|
Back to top |
|
|
simhau
Joined: 06 Feb 2007 Posts: 55
|
Posted: Mon Jan 14, 2008 8:10 am Post subject: |
|
|
Yeah, I figured the binding library is a bit lacking.
When wrapping derived classes I couldn't find a way to ensure methods and properties wrapped in the base class automatically gets wrapped... It's a bit tedious and error prone to wrap all base class functionality for all derived classes.
Guess the binding library is going to be redesigned again for MD2? |
|
Back to top |
|
|
JarrettBillingsley
Joined: 20 Jun 2006 Posts: 457 Location: Pennsylvania!
|
Posted: Mon Jan 14, 2008 10:16 am Post subject: |
|
|
Derived classes will inherit everything from their base class. That's guaranteed. |
|
Back to top |
|
|
simhau
Joined: 06 Feb 2007 Posts: 55
|
Posted: Mon Jan 14, 2008 11:07 am Post subject: |
|
|
I cannot get it to work
Code: | module test;
import tango.io.Stdout;
import minid.minid;
import minid.bind;
import minid.types;
class B {
int i() { return _i; }
void i(int i) { _i = i; }
protected:
int _i;
}
class D : B {
int y() { return _y; }
void y(int y) { _y = y; }
protected:
int _y;
}
void main()
{
auto ctx = NewContext(
MDStdlib.Array
| MDStdlib.Char
| MDStdlib.Math
| MDStdlib.String
| MDStdlib.Table);
WrapModule("test", ctx)
.type(WrapClass!(B)()
.property!(B.i)()
)
.type(WrapClass!(D)()
.property!(D.y)()
)
;
try {
Stdout.formatln("Loading script");
ctx.importModule("mdtest"d);
} catch(MDException e) {
Stdout.formatln("Error: {}\n{}", e.toString(), ctx.getTracebackString());
}
Stdout.formatln("Script finished");
}
|
Code: | module mdtest;
import test : B, D;
local b = B();
b.i(1);
writefln("B.i=", b.i());
local d = D();
d.y(2);
writefln("D.y=", d.y());
d.i(1);
writefln("D.i=", d.i());
|
This outputs
Loading script
B.i=1
D.y=2
Error: Error loading module "mdtest":
mdtest.module mdtest(11:25): Attempting to access nonexistent member 'i' from class instance
Traceback: mdtest.module mdtest(11:25)
Script finished |
|
Back to top |
|
|
JarrettBillingsley
Joined: 20 Jun 2006 Posts: 457 Location: Pennsylvania!
|
Posted: Mon Jan 14, 2008 2:24 pm Post subject: |
|
|
OK, that's odd, it's not minid.bind that broken but for some reason it wraps D before it wraps B when the module is loaded, so B isn't found as the base class for D. I would have expected the chained methods to be executed left-to-right.
A simple fix:
Code: | with(WrapModule("test", ctx))
{
type(WrapClass!(B)()
.property!(B.i)()
);
type(WrapClass!(D)()
.property!(D.y)()
);
} |
I'll have to do some more testing to see why the chained methods are getting called in reverse order.. I mean, it doesn't do that when using i.e. Tango IO! |
|
Back to top |
|
|
JarrettBillingsley
Joined: 20 Jun 2006 Posts: 457 Location: Pennsylvania!
|
Posted: Mon Jan 14, 2008 2:52 pm Post subject: |
|
|
OK, with some more testing, it's not that the methods are being called backwards, it's that their arguments are being evaluated backwards before they're even called. Big WTF moment there.
Code: | WrapModule("blah", ctx).type(WrapClass!(A)()).type(WrapClass!(B)()); |
happens in the following order:
- temp b = WrapClass!(B)()
- temp a = WrapClass!(A)()
- temp m = WrapModule("blah", ctx)
- m.type(a)
- m.type(b)
So even though the methods are called in the correct order, their params are evaluated before they're called in the wrong order.
Scary corner cases in order-of-evaluation. |
|
Back to top |
|
|
simhau
Joined: 06 Feb 2007 Posts: 55
|
Posted: Tue Jan 15, 2008 6:08 am Post subject: |
|
|
Aha.
This deserves some documentation. It's more natural to start by wrapping baseclasses, so I guess I'm not the only one getting this behaviour. |
|
Back to top |
|
|
csauls
Joined: 27 Mar 2004 Posts: 278
|
Posted: Tue Jan 15, 2008 9:26 pm Post subject: |
|
|
I find this rather surprising... I would expect code generation to follow the order of data necessity; which in your example and list would seem to be numbers 3, 2, 4, 1, then 5. Quite a difference!
Its just this sort of occasional bump in the road that motivates me to test every micro-design with some short throw-away program first. This is one of those 'corner cases' that you may want to make sure you mention in the MiniD docs -- since I'm sure it will come up again and again as it gains more usage.
And it might not hurt to get an explanation on why it occurs in this order. _________________ Chris Nicholson-Sauls |
|
Back to top |
|
|
JarrettBillingsley
Joined: 20 Jun 2006 Posts: 457 Location: Pennsylvania!
|
Posted: Wed Jan 16, 2008 9:02 am Post subject: |
|
|
Posted on the D NG. |
|
Back to top |
|
|
|