[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-bindings
Subject: Re: [Kde-bindings] I need help with SMOKE (trying to write bindings
From: Ashley Winters <jahqueel () yahoo ! com>
Date: 2005-10-10 1:08:18
Message-ID: 20051010010819.43099.qmail () web50910 ! mail ! yahoo ! com
[Download RAW message or body]
--- Clifford Wolf <clifford@clifford.at> wrote:
> Hi,
>
> I'm trying to write Qt+KDE bindings for SPL
> (http://www.clifford.at/spl/)
> using SMOKE. My idea was to first write a little C program which only
> implemnts those parst of the iterface required for a little "Hello
> World"
> program, than make it an SPL module and finally add the missing code
> for
> the bindings to be complete.
>
[...]
> I think with this two informations I should be able to write a small
> app
> which does the following with the SMOKE wrapper library:
>
> #include <qt3/qapplication.h>
> #include <qt3/qlabel.h>
>
> int main(int argc, char **argv)
> {
> QApplication *a = new QApplication(argc, argv);
> QWidget *l = new QLabel("Hello World!", NULL);
> a->setMainWidget(l);
> l->show();
> a->exec();
> return 0;
> }
I attached a working version of that program using Smoke. It's written
so that you don't link directly to -lsmokeqt, but dlopen() it. Ideally,
that would be portable, but the init() function isn't declared as
extern "C". The portable way is to link with -lsmokeqt directly, but I
don't really like that. Oh well. If Richard can patch Smoke with a new
version of the init() function, that'd be nifty:
extern void init_qt_Smoke();
extern "C" init_libsmokeqt() { init_qt_Smoke(); }
Compile with:
g++ -g -o hello hello.c -lqt-mt
and make sure you have libsmokeqt installed where it can be found --
either in your default lib path, or by setting LD_LIBRARY_PATH
Cheers,
Ashley Winters
__________________________________
Yahoo! Mail - PC Magazine Editors' Choice 2005
http://mail.yahoo.com
["hello.c" (text/x-csrc)]
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <qt3/qstring.h>
#include "smoke.h"
// don't add any behaviors -- just let everything work
class MySmokeBinding : public SmokeBinding {
public:
MySmokeBinding(Smoke *s) : SmokeBinding(s) {}
virtual void deleted(Smoke::Index, void*) {
// ignore object deletion
}
virtual bool callMethod(Smoke::Index, void*, Smoke::Stack, bool) {
return false; // decline all offers to override a virtual function
}
virtual char *className(Smoke::Index classId) {
// return a new[] copy of the language-specific name of this Smoke class
// poorly designed function, but oh well. Sorry.
const char *className = smoke->className(classId);
char *buf = new char[strlen(className) + 1];
strcpy(buf, className);
return buf;
}
virtual ~MySmokeBinding() {}
};
// call init function, and return the master Smoke* object
Smoke *init_smoke() {
typedef void (*smoke_init_func)();
void *lib = dlopen("libsmokeqt.so.1", RTLD_NOW);
if(!lib) {
fprintf(stderr, "Unable to open Smoke: %s", dlerror());
exit(-1);
}
smoke_init_func init = (smoke_init_func)dlsym(lib, "init_libsmokeqt"); /* \
extern "C" version -- requires latest version */ if(!init) init = \
(smoke_init_func)dlsym(lib, "_Z13init_qt_Smokev"); /* Linux ABI version -- old */ \
if(!init) { dlclose(lib);
return 0;
}
init();
void *qt_smoke = dlsym(lib, "qt_Smoke");
return *(Smoke**)qt_smoke;
}
// given class-name and mangled function-name, return an unambiguous method ID
Smoke::Index getMethod(Smoke *smoke, const char* c, const char* m) {
Smoke::Index method = smoke->findMethod(c, m);
Smoke::Index i = smoke->methodMaps[method].method;
if(i <= 0) {
// ambiguous method have i < 0; it's possible to resolve them, see the other \
bindings fprintf(stderr, "%s method %s::%s\n",
i ? "Ambiguous" : "Unknown", c, m);
exit(-1);
}
return i;
}
// call obj->method(args)
void callMethod(Smoke *smoke, void *obj, Smoke::Index method, Smoke::Stack args) {
Smoke::Method *m = smoke->methods + method;
Smoke::ClassFn fn = smoke->classes[m->classId].classFn;
fn(m->method, obj, args);
}
// cast argument pointer to the correct type for the specified method argument
// args[i].s_class = (void*)(typeof(args[i]))(className*)obj
void smokeCast(Smoke *smoke, Smoke::Index method, Smoke::Stack args, Smoke::Index i, \
void *obj, const char *className) { // cast obj from className to the desired type \
of args[i] Smoke::Index arg = smoke->argumentList[
smoke->methods[method].args + i - 1
];
// cast(obj, from_type, to_type)
args[i].s_class = smoke->cast(obj, smoke->idClass(className), \
smoke->types[arg].classId); }
// cast obj to the required type of this, which, dur to multiple-inheritance, could \
change the pointer-address // from the one returned by new. Puts the pointer in \
args[0].s_class, even though smoke doesn't do it that way void smokeCastThis(Smoke \
*smoke, Smoke::Index method, Smoke::Stack args, void *obj, const char *className) { \
args[0].s_class = smoke->cast(obj, smoke->idClass(className), \
smoke->methods[method].classId); }
int main(int argc, char **argv) {
Smoke *smoke = init_smoke();
smoke->binding = new MySmokeBinding(smoke);
void *qapp;
{
// new QApplication(argc, argv)
Smoke::Index method = getMethod(smoke, "QApplication", "QApplication$?");
Smoke::StackItem args[3];
args[1].s_voidp = (void*)&argc;
args[2].s_voidp = (void*)argv;
callMethod(smoke, 0, method, args);
qapp = args[0].s_class;
}
void *l;
{
// new QLabel(QString("Hello World!"), (QWidget*)0)
Smoke::Index method = getMethod(smoke, "QLabel", "QLabel$#");
Smoke::StackItem args[3];
QString s("Hello World!");
args[1].s_voidp = (void*)&s;
args[2].s_class = 0;
callMethod(smoke, 0, method, args);
l = args[0].s_class;
}
{
// qapp->setMainWidget(l)
Smoke::Index method = getMethod(smoke, "QApplication", "setMainWidget#");
Smoke::StackItem args[2];
smokeCast(smoke, method, args, 1, l, "QLabel");
smokeCastThis(smoke, method, args, qapp, "QApplication");
callMethod(smoke, args[0].s_class, method, args);
}
{
// l->show()
Smoke::Index method = getMethod(smoke, "QLabel", "show");
Smoke::StackItem args[1];
smokeCastThis(smoke, method, args, l, "QLabel");
callMethod(smoke, args[0].s_class, method, args);
}
{
// return qapp->exec()
Smoke::Index method = getMethod(smoke, "QApplication", "exec");
Smoke::StackItem args[1];
smokeCastThis(smoke, method, args, qapp, "QApplication");
callMethod(smoke, args[0].s_class, method, args);
return args[0].s_int;
}
}
_______________________________________________
Kde-bindings mailing list
Kde-bindings@kde.org
https://mail.kde.org/mailman/listinfo/kde-bindings
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic