[Kde-bindings] Using smoke with ffi to C

Richard Dale Richard_Dale at tipitina.demon.co.uk
Tue Oct 10 12:59:59 UTC 2006


On Monday 09 October 2006 18:29, Paulo J. Matos wrote:
> Hi all,
>
> How can I use smoke to create bindings for Qt/KDE if the language ffi
> I'm using only accesses C correctly?
>
> The example
> http://cablemodem.fibertel.com.ar/lateral/weblog/2005/12/16.html
>
> uses C++.
> I've also downloaded QtRuby but this one was just to see if it would
> clarify how smoke works... but still since I don't understand ruby I
> was not really able to understand what architecture they are using to
> create the bindings. Correct me if I'm wrong: In QtRuby they create a
> C++ extension to the Ruby compiler to call smoke and then use it in
> ruby to create the bindings. Is it?
Ruby itself only has a C interface, and so there are C functions to interface 
directly with Ruby which contain C++ code that in turn interfaces with the 
Smoke lib. You use the Smoke lib by looking up a pointer to a function to 
call given the target methodname as a string, plus a single character for 
each arg which is an approximation of it's type (called the 'munged method 
name'). If you only have one match returned, you can call the function 
pointer. It there is more than one possible match because the method is 
overloaded you need to resolve the ambiguity be matching the types of the 
arguments in the bindings language against the C++ types of the target 
method. You need to marshall arguments from the bindings language to C++ as 
an array of unions called the 'Smoke::Stack'.

Here is an example, calling a method called qt_metacall().

qt_metacall(QMetaObject::Call _c, int id, void ** _o)

The munged method name is 'qt_metacall$$?', and an int id representing the 
class is in 'o->classId' (there is a function in the Smoke lib to look up the 
id of a class, given its name as a string). 'o->ptr' contains a pointer to 
the C++ instance to invoke the method on, and so you need a way of retrieving 
the C++ instance corresponding to an instance in the bindings language.

		Smoke::Index nameId = o->smoke->idMethodName("qt_metacall$$?");
		Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
		if (meth > 0) {
			Smoke::Method &m = o->smoke->methods[o->smoke->methodMaps[meth].method];
			Smoke::ClassFn fn = o->smoke->classes[m.classId].classFn;
			Smoke::StackItem i[4];
			i[1].s_enum = _c;
			i[2].s_int = id;
			i[3].s_voidp = _o;
			(*fn)(m.method, o->ptr, i);
			return INT2NUM(i[0].s_int);
		}

The zeroth element of the Smoke::Stack is used to hold the reply value from 
the method call, and here it is converted from a C++ int to a Ruby Integer by 
the 'INT2NUM' macro.

-- Richard



More information about the Kde-bindings mailing list