--0-1781599545-1128906498=:42293 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Content-Id: Content-Disposition: inline --- Clifford Wolf 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 > #include > > 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 --0-1781599545-1128906498=:42293 Content-Type: text/x-csrc; name="hello.c" Content-Description: 3578776425-hello.c Content-Disposition: inline; filename="hello.c" #include #include #include #include #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; } } --0-1781599545-1128906498=:42293 Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline _______________________________________________ Kde-bindings mailing list Kde-bindings@kde.org https://mail.kde.org/mailman/listinfo/kde-bindings --0-1781599545-1128906498=:42293--