[Kde-bindings] Qyoto gets better...

Richard Dale Richard_Dale at tipitina.demon.co.uk
Wed Nov 30 19:39:56 UTC 2005


On Wednesday 30 November 2005 18:40, Arno Rehn wrote:
> Am Dienstag, 29. November 2005 12:33 schrieb Richard Dale:
> > On Monday 28 November 2005 21:25, Arno Rehn wrote:
> > > Am Montag, 28. November 2005 13:44 schrieb Arno Rehn:
> > > > Hi,
> > > >
> > > > Ok, with the last update there's some progress. Now I don't get some
> > > > Index out of range error anymore, but it still doesn't work:
> > > >
> > > > Invoke() MethodName: NewQApplication Type: Qt.QApplication, hello,
> > > > Version=0.0.0.0, Culture=neutral, PublicKeyToken=null ArgCount: 2
> > > > FindMethod() className: QApplication MethodName: QApplication$?
> > > >                 In FindMethodId QApplication::QApplication$? => 146
> > > > FindMethod() MethodName: QApplication$? result: 154
> > > >         ArgName: argc Arg: 0 Type: System.Int32		//hmm... Arg:0 I
> > > > think, the path to the executable is already an argument ?!
> > > >
> > > >         ArgName: argv Arg: System.String[] Type: System.String[]
> > > > In CallMethod methodId: 154 target: 0x00000003 items: 2
> > > > In CallMethod 0		// seems not to be right
> > > > In CallMethod classId: 123
> > > > result 999		// was not correctly called
> > > >
> > > > Invoke() MethodName: NewQDialog Type: Qt.QDialog, hello,
> > > > Version=0.0.0.0, Culture=neutral, PublicKeyToken=null ArgCount: 0
> > > > FindMethod() className: QDialog MethodName: QDialog
> > > >                 In FindMethodId QDialog::QDialog => 2022
> > > > FindMethod() MethodName: QDialog result: 2144
> > > > In CallMethod methodId: 2144 target: 0x00000003 items: 0
> > > > In CallMethod 137193560
> > > > In CallMethod classId: 123
> > > > result 999
> > > > // this is called properly, but with no proper initialization of a
> > > > QApplication it doesn't run.
> > > >
> > > >
> > > > I modified the QApplication-Constructor to pass the Proxy an argc
> > > > with a "Length + 1". Then the output says "ArgName: argc Arg: 1 Type:
> > > > System.Int32" and "In CallMethod 1" instead of "In CallMethod 0".
> > > > This seems to be better, but not good.
> >
> > Yes, I'm not sure if C# has the program name in argv[0] or not - so maybe
> > that needs adding before calling the C++ method that is expecting it to
> > be there.
> >
> > > I think I have to take a look in the source-code before I say something
> > > here. The "result 999" has to do nothing with the execution of a
> > > method, that is hardcoded into the libqyoto.so. But why is the mehtod
> > > not successfully called when there's more than one argument? I'll have
> > > a closer look at the Qt.cpp from qtruby. Maybe that helps a bit.
> >
> > Yes, stuff like the hard coded result is there just to demonstrate that
> > it's possible to return a result back to C#. I'll try and post an
> > explanation of what it's all about, and what is missing when I've time -
> > it is very similar to qtruby though, so it won't do any harm to look at
> > that code.
> >
> > -- Richard
>
> Thistime I took a closer look at the source. I don't understand the
> CallMethod() in qyoto.cpp / qt3qyoto.cpp. Everything goes right until one
> of the called Methods from the helloworld-example have any arguments. The
> arguments are correctly passed to CallMethod(), but nothing is done with
> them. What is done with "Smoke::StackItem * sp" ? You just print some
> values on the console, but nothing else is done. As this variable contains
> the arguments I wonder how this works.
The Smoke::StackItem is an item in the array of C++ args that is passed when 
you call a method in the Smoke library.

This loop is moving things from the array passed to SmokeInvocation.Invoke():

				for (int i = 0; i < callMessage.ArgCount; i++) {
					if (types[i] == typeof(bool)) {
						stack[i+1].s_bool = (bool) callMessage.Args[i];
					} else if (types[i] == typeof(sbyte)) {
						stack[i+1].s_char = (sbyte) callMessage.Args[i];
					} else if (types[i] == typeof(byte)) {
						stack[i+1].s_uchar = (byte) callMessage.Args[i];
					} else if (types[i] == typeof(short)) {
						stack[i+1].s_short = (short) callMessage.Args[i];
					} else if (types[i] == typeof(ushort)) {
						stack[i+1].s_ushort = (ushort) callMessage.Args[i];
					} else if (types[i] == typeof(int)) {
						stack[i+1].s_int = (int) callMessage.Args[i];
					} else if (types[i] == typeof(uint)) {
						stack[i+1].s_uint = (uint) callMessage.Args[i];
					} else if (types[i] == typeof(long)) {
						stack[i+1].s_long = (long) callMessage.Args[i];
					} else if (types[i] == typeof(ulong)) {
						stack[i+1].s_ulong = (ulong) callMessage.Args[i];
					} else if (types[i] == typeof(float)) {
						stack[i+1].s_float = (float) callMessage.Args[i];
					} else if (types[i] == typeof(double)) {
						stack[i+1].s_double = (double) callMessage.Args[i];
					} else if (types[i] == typeof(string[])) {
						unsafe {
							stack[i+1].s_voidp = (void *) StringArrayToCharStarStar((string[]) 
callMessage.Args[i]);
						}
					}

What's missing is the one to set up the s_class entry for something like a 
QWidget. It needs to be a GCHandle, and over on the C/C++ side the 
corresponding C++ instance needs to be looked up and marshalled to the 
s_class field in the SmokeStack as a 'void *'.

Here is the QtRuby code to call a method (from the method_missing() function 
in Qt.cpp):

    MethodCall c(qt_Smoke, _current_method, self, temp_stack+4, argc-1);
    c.next();
    VALUE result = *(c.var());

There is a C++ class called 'MethodCall' in qt3qyoto.cpp too, and so that 
needs to be passed the SmokeStack, once it is correctly set up. We already 
have the correct method lookup in the Smoke library.

I'll post some more explanation ASAP - I'm afraid the net has been down for 
the last couple of days after a storm here in the Canaries. I'm still 
catching up with everything.

-- Richard



More information about the Kde-bindings mailing list