[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