QtScript plus enums - qt

I am adding QScript to my Qt application. I have already added metadata and use some of the metadata functions to interrogate through C++ code. That works fine - I can navigate the object heirarchy and print out values (including enums).
But, I can't seen to get enums working in Qt script.
I have my class...
class HalPin : public QObject
{
Q_OBJECT
public:
enum EHalPinType
{
Bit = HAL_BIT,
Float = HAL_FLOAT,
S32 = HAL_S32,
U32 = HAL_U32
};
enum EHalPinDirection
{
In = HAL_IN,
Out = HAL_OUT,
IO = HAL_IO
};
Q_ENUMS(EHalPinType)
Q_ENUMS(EHalPinDirection)
public:
explicit HalPin(QObject *parent = 0);
signals:
public slots:
};
Q_DECLARE_METATYPE(HalPin::EHalPinType)
Q_DECLARE_METATYPE(HalPin::EHalPinDirection)
Q_DECLARE_METATYPE(HalPin*)
I have another class that has a method that takes the enums as arguments...
class EmcHal : public QObject
{
Q_OBJECT
public:
explicit EmcHal(QString moduleName, QObject *parent = 0);
signals:
public slots:
QObject *createHalPin( HalPin::EHalPinType, HalPin::EHalPinDirection, QString name );
};
This class is exposed in another class - sorry I should have simplified the example. If I write the following jscript code,
var nextPagePin1 = Emc.hal.createHalPin();
I get an error I expect...
SyntaxError: too few arguments in call to createHalPin(); candidates are createHalPin(HalPin::EHalPinType,HalPin::EHalPinDirection,QString)
So, it appears that the enum types are known to qtscript.
What I am struggling to do is to set the enum arguments from jscript. I've tried many combinations...
Bit
EHalPinType.Bit
HalPin.EHalPinType.Bit
and many more.
If I try to use integers, I get...
TypeError: cannot call createHalPin(): argument 1 has unknown type `HalPin::EHalPinType' (register the type with qScriptRegisterMetaType())
which seems to imply jscript doesn't know about my enums.
Any suggestions?
Do I need to use qRegisterMetaType or qScriptRegisterMetaType to access my enums? The documentation doesn't suggest I need to do this. Do I need to implement the converter functions for the qScriptRegisterMetaType method.
Or is my syntax just wrong for the jscript?
Does someone have a working example?
Thanks,
Frank

To answer my own question...
Well, not so much an answer to why, but a "meh, this works" example...
As I mentioned above, I wasn't able to get the enums working in both the metadata and jscript at the same time using the qt macros. Even though the enum appeared in qscript (I checked in the browser of the script debugger), it didn't evaluate to the correct integer.
I had to add a QMetaObject for the enum. That gave me the enum items, and correct integer values.
But that still gave me the unknown type error, so I needed to use qScriptRegisterMetaType() to register conversion functions for the types.
This is the class I use for 1 enum. It is as minimal as I can make it. I should be able to use macros to shrink it down a bit more, but there are limitations on what can be macroised, because of the qt moc requirements.
#include <QObject>
#include <QMetaType>
#include <QScriptEngine>
#include "hal.h"
class CEHalPinType : public QObject
{
Q_OBJECT
public:
explicit CEHalPinType(QObject *parent = 0) : QObject(parent) {}
explicit CEHalPinType(const CEHalPinType &other) : QObject(other.parent()) {}
virtual ~CEHalPinType() {}
enum EHalPinType
{
Bit = HAL_BIT,
Float = HAL_FLOAT,
S32 = HAL_S32,
U32 = HAL_U32
};
Q_ENUMS( EHalPinType )
private:
static QScriptValue toScriptValue(QScriptEngine *engine, const EHalPinType &s)
{
return engine->newVariant((int)s);
}
static void fromScriptValue(const QScriptValue &obj, EHalPinType &s)
{
s = (EHalPinType)obj.toInt32();
}
static QScriptValue qscriptConstructor( QScriptContext *context, QScriptEngine *engine )
{
return engine->newQObject( new CEHalPinType(context->argument(0).toQObject()), QScriptEngine::ScriptOwnership);
}
public:
static void Init( const char *name, QScriptEngine *engine )
{
qScriptRegisterMetaType(engine, toScriptValue, fromScriptValue);
QScriptValue metaObject = engine->newQMetaObject( &staticMetaObject, engine->newFunction(qscriptConstructor) );
engine->globalObject().setProperty( name, metaObject );
}
};
Q_DECLARE_METATYPE(CEHalPinType::EHalPinType)
And my jscript looks like...
var nextPagePin = Emc.hal.createHalPin(EHalPinType.Bit,EHalPinDirection.In,"nexis.NextPage");

Oops. I jumped the gun on this one. Although the scripting worked, I broke the ability to convert enums to strings using the qmetaobject data.
And there doesn't seem to be an automatic way of doing it.
The problem is, I moved the enums out of the class where the properties that used the enums were defined. Although the Q_ENUMS and Q_PROPERTY compile, if I use the QMetaProperty to to read an enum, it doesn't work. The QVariant that is returned shows the correct data type, "CEHalPinType::EHalPinType", but it fails the isEnum() test and canConvert(QVariant::String) fails too. This is because when the qmetaobject code goes searching for the enum type, it only looks in the current class and its derived classes. It doesn't search other classes. Which is why it worked when the enum was a member of the class which also had the properties.
My work around, as suggested elsewhere, was to create my own QMap of known enums, storing the string name to qmetaobject mapping. I used a templated base class and used T::staticMetaObject to get the meta object.

Related

QVariant call a function of a stored object, defined in the main part of a project

The common part (crating a lib) of my project currently holds a interface Class of the type:
class CanBeAddedToGroup{
public:
void addToGroup(Group& )=0;
}
Now i also wantred to use the programm on a Class containing data in a QVariant, so i started it off simple:
class DataContainingClass: public CanBeAddedToGroup{
QMap<QString,QVarient> data;
public:
void addToGroup(Group& ){
QMap<QString,QVarient>::itterator itter = data.begin();
QMap<QString,QVarient>::itterator end= data.end();
for(;itter !=end;itter ++){
<Handle Data>
}
}
};
}
Now one of the datatypes addedt to the list (outside the lib) is of the type:
class DataClass: public QObject, public CanBeAddedToGroup{
void addToGroup(Group& );
}
Q_DECLARE_METATYPE(DataClass)
And it is added to the map using "QVariant::fromValue(", now i need a way in the "DataContainingClass" to check if the Data is derived from a QObject, so i know static_cast(variant.data()) is valid.
Then i could try to dynamic_cast the Object pointer to CanBeAddedToGroup, and call it.
--- EDIT ---:
The Problem IS NOT: Having a QObject and check if it inherits another QObject, it is not even checking if a Class inherits from another one, it is to know if the data i have actually IS a QObject.
Minimal Example:
Header File:
#include <QObject>
#include <QDebug>
class DmbClass: public QObject{
Q_OBJECT
public:
DmbClass(){TST="RealOne";}
DmbClass(const DmbClass&d){TST="Clone";}
QString TST;
};
Q_DECLARE_METATYPE(DmbClass)
class Tst{
public:
virtual void tstFunct()=0;
};
class CanClass: public QObject, public Tst{
Q_OBJECT
public:
CanClass(){TST="RealOne";}
CanClass(const CanClass&d){TST="Clone";}
QString TST;
virtual void tstFunct() override{
qDebug()<<"tst";
}
};
Q_DECLARE_METATYPE(CanClass)
class DmbGadget{
Q_GADGET
public:
DmbGadget(){TST="RealOne";}
DmbGadget(const DmbGadget&d){TST="Clone";}
QString TST;
};
Q_DECLARE_METATYPE(DmbGadget)
C File:
// QObject in QVariant
DmbClass dC;
QVariant varC=QVariant::fromValue(dC);
const void* vPC = varC.data();
DmbClass dCc = varC.value<DmbClass>();
QObject* objC = (QObject*)varC.data();
QObject* schouldWork = objC->parent();
Tst* schouldBeNull = dynamic_cast<Tst*>(objC);
// Object using correct base class in QVariant
CanClass dT;
QVariant varT=QVariant::fromValue(dT);
const void* vPT = varT.data();
CanClass dTc = varC.value<CanClass>();
QObject* objT = (QObject*)varT.data();
QObject* schouldWork2 = objT->parent();
Tst* schouldNotNull = dynamic_cast<Tst*>(objT);
schouldNotNull->tstFunct();
// Q_Gadget in QVariant
DmbGadget dG;
QVariant varG=QVariant::fromValue(dG);
const void* vPG = varG.data();
DmbGadget dGg = varG.value<DmbGadget>();
QObject* objD = (QObject*)varG.data();
//QObject* schouldSegFault = objD->parent();
// base value in QVariant
QVariant var4=4;
const void* vP4 = var4.data();
QObject* obj4 = (QObject*)var4.data();
//QObject* schouldSegFault2 = obj4 ->parent();
I need a way to distinguisch cases 1&2 from 3&4 ("schouldSegFault"), without using something only defined outside of the lib.
I Already Tryed:
int tst4 = qRegisterMetaType<CanClass>("CanClass");
QMetaType help2(tst4);
But help2 has a MetaObject of 0, so i cant check for the inheriance from QObject.
Edit/for who added "Proper way to check QObject derived class type in Qt" ther was te issue in my programm that the class inherits from another QObjectclass so i cant chack for inheriance of my interface (even when defined as Q_Gadget) using inherits, since it would only be true for the first element.
PS: For everyone trying to call functions on a QVariant containing a Object rather than a pointer might be interested in this approach:
How to support comparisons for QVariant objects containing a custom type? / https://pastebin.com/tNLa0jSa
While having a global registry for types is what i wished i could avoid for the case.
Just try to use QVariant::value and see if the value in a QVariant can be converted to your target class. Here's a minimal example:
#include <QObject>
#include <QVariant>
#include <QVariantMap>
#include <QDebug>
class MyQObjectClass : public QObject {
Q_OBJECT
public:
explicit MyQObjectClass(QObject *parent = nullptr) : QObject(parent) {}
void greet() { qDebug() << "I am a MyQObjectClass!"; }
};
Q_DECLARE_METATYPE(MyQObjectClass*)
int main(int, char *[])
{
MyQObjectClass obj;
QVariantMap map;
map.insert("foo", QString("Hello World"));
map.insert("bar", QVariant::fromValue(&obj));
QVariantMap::iterator iter = map.begin();
QVariantMap::iterator end= map.end();
for(;iter !=end;iter ++) {
auto value = iter.value();
// Try to convert to MyQObjectClass*
auto obj = value.value<MyQObjectClass*>();
if (obj != nullptr) {
qDebug() << iter.key() << "is an instance of MyQObjectClass";
obj->greet();
continue;
}
qDebug() << iter.key() << "is not an instance of MyQObjectClass";
}
}
#include "main.moc"
Running it should yield the following output on the console:
"bar" is an instance of MyQObjectClass
I am a MyQObjectClass!
"foo" is not an instance of MyQObjectClass
The important parts:
Make sure the class you want to store in a QVariant derives from QObject and has the Q_OBJECT macro.
When iterating over the map, use QVariant::value() and try to convert the contained value to your target class. In the example, I use QVariant::value<MyQObjectClass*>() - according to the documentation, this either returns the contained instance of MyQObjectClass* if the value can be converted to it or - which is the case if the QVariant contains either basic values or gadgets - a default constructed value. In the case of a pointer this would be a null pointer, so just check if the value returned is null. That's it.
Never work on Qvariant::data() directly.
Update
Just as a remark: The Qobject class declared the copy constructor and assignment operators as private:
From the official documentation:
QObject has neither a copy constructor nor an assignment operator. This is by design. Actually, they are declared, but in a private section with the macro Q_DISABLE_COPY(). In fact, all Qt classes derived from QObject (direct or indirect) use this macro to declare their copy constructor and assignment operator to be private. The reasoning is found in the discussion on Identity vs Value on the Qt Object Model page.
Hence, you cannot copy around instances of QObject (and consequentially you cannot store them in QVariant). Instead, you pass around pointers to QObject instances.
Update #2
If your interface class cannot derive directly from QObject, you might consider using Qt's plugin mechanism instead. Here's the above example slightly edited to fit this approach:
#include <QObject>
#include <QVariant>
#include <QVariantMap>
#include <QDebug>
class MyInterfaceClass {
public:
MyInterfaceClass() {}
virtual ~MyInterfaceClass() {}
virtual void greet() = 0;
};
#define MyInterfaceClass_IID "org.example.MyInterfaceClass"
Q_DECLARE_INTERFACE(MyInterfaceClass, MyInterfaceClass_IID)
class MyConcreteClass : public QObject, public MyInterfaceClass {
Q_OBJECT
Q_INTERFACES(MyInterfaceClass)
public:
MyConcreteClass(QObject *parent = nullptr) : QObject(parent) {}
void greet() override { qDebug() << "I am a MyInterfaceClass!"; }
};
int main(int, char *[])
{
MyConcreteClass obj;
QVariantMap map;
map.insert("foo", QString("Hello World"));
map.insert("bar", QVariant::fromValue(&obj));
QVariantMap::iterator iter = map.begin();
QVariantMap::iterator end= map.end();
for(;iter !=end;iter ++) {
auto value = iter.value();
// Try to convert to QObject*:
auto obj = value.value<QObject*>();
if (obj != nullptr) {
// Try if we can cast to our interface class:
auto ifc = qobject_cast<MyInterfaceClass*>(obj);
if (ifc != nullptr) {
qDebug() << iter.key() << "is an instance of MyInterfaceClass";
ifc->greet();
}
continue;
}
qDebug() << iter.key() << "is not an instance of MyInterfaceClass";
}
}
#include "main.moc"
You need to:
Define your interface class and register it with Qt using the Q_DECLARE_INTERFACE macro.
Declare your concrete classes, deriving from QObject and your interface class. In addition, you need to tell Qt about the interface part using the Q_INTERFACES macro.
When checking the values in your map, first try to convert to a QObject* via QVariant::value(). If this succeeds, you can try to qobject_cast to your interface class.
Your design is completely broken: QObjects cannot be used as unrestricted values. They cannot be copied nor moved, and your implementations of copy constructors are hiding this fundamental fact.

Qt Meta System Call constructor with parameters

I know that I can use QMetaType to create an object without parameters.
Another possible option is to use QMetaObject and call newInstance. But I need to get QMetaObject from something.
I tried to use QMetaType::metaObjectForType, but it always returns null pointer (but QMetaType is able to create the object).
QMetaObject const* metaObject = QMetaType::metaObjectForType(id); // return null pointer
QObject* object = (QObject*)QMetaType::create(id); // create the object
QMetaObject const* metaObject = object->metaObject(); // return not-null pointer
UPDATE:
I think the question is why metaObjectForType does not work for me.
The class is registered with qRegisterMetaType, also Q_DECLARE_METATYPE and Q_OBJECT are applied.
First of all, to pass parameters to methods, you needs some kind of reflection framework beyond plain C++. With Qt, the obivous choice is Qt Meta Object system with it's QMetaObject, though then you must derive your classes for QObject. After that, you need to do two things:
1. make constructor invokable
Signals and slots are invokable by default, but any other method you want to invoke through the meta object system needs to be explicitly marked as such. Example myqobject.h:
#ifndef MYQOBJECT_H
#define MYQOBJECT_H
#include <QObject>
class MyQObject : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyQObject(QObject *parent = 0); // tested with empty constructor in .cpp
};
#endif // MYQOBJECT_H
2. create your own mapping from class name string to the QMetaObject
QMetaType doc says: "any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered." This rules out QObject, because they can't have copy constructors. You need to create your own mapping from name to the meta object. An example shown in this main.cpp:
#include <QCoreApplication>
#include <QtCore>
#include "myqobject.h"
// a global map for mapping strings to QMetaObjects,
// you need header file like this if you want to access it from other .cpp files:
//
// #include <QHash>
// #include <QString>
// class QMetaObject; // forward declaration, enough when only pointer is needed
// extern QHash<QString, const QMetaObject*> metaObjs;
//
QHash<QString, const QMetaObject*> metaObjs;
// optional: create a macro to avoid typing class name twice,
// #c surrounds macro argument with double quotes converting it to string
#define METAOBJS_INSERT(c) (metaObjs.insert(#c, &c::staticMetaObject))
int main()
{
METAOBJS_INSERT(MyQObject);
const QMetaObject *meta = metaObjs["MyQObject"];
qDebug() << "Class name from staticMetaObject: " << meta->className();
QObject *o = meta->newInstance(); // add constructor arguments as needed
MyQObject *mo = qobject_cast<MyQObject*>(o);
if (mo) qDebug() << "Class name from object instance: " << mo->metaObject()->className();
else qDebug() << "Instance creation failed or created wrong class!";
return 0;
}
If you do not want to use QObject, then you need to come up with some similar (probably lighter-weight and without separate compiler step) mechanism of your own.
I had the same problem.
The solution is in two steps:
call qRegisterMetaType() with a pointer type:
qRegisterMetaType<MyClass*>(). this will give you a valid
QMetaObject with call of QMetaType::metaObjectForType(id);
make your constructor Q_INVOKABLE. this will enable a valid call to
QMetaObject::newInstance
And also be sure that your class is derived from QObject and have a Q_OBJECT macro in it.
class A : public QObject
{
Q_OBJECT
public:
A(const A&) {}; // dummy copy contructor that do nothing to disable error message
Q_INVOKABLE A(int test_value = 99999) : TestValue(test_value) {};
int TestValue;
};
Q_DECLARE_METATYPE(A);
int main(int argc, char *argv[])
{
qRegisterMetaType<A>(); //you do not need this
qRegisterMetaType<A*>();//the real registration
int type_id_for_A = QMetaType::type("A"); // valid type id (in my case = 403)
const QMetaObject *meta_object_for_A = QMetaType::metaObjectForType(type_id_for_A); // returns NULL
int type_id_for_A_ptr = QMetaType::type("A*"); // valid type id (in my case = 404)
const QMetaObject *meta_object_for_A_tr = QMetaType::metaObjectForType(type_id_for_A_ptr); // returns NOT NULL
A* A_obj= dynamic_cast<A*>(meta_object_for_A_tr->newInstance(Q_ARG(int, 12345)));
int test_value = A_obj->TestValue; // returns 12345, not 99999
}

Naming attributes and methods in Qt

I'd like to have this:
class Test {
private:
int a;
public:
int a();
int setA(int val);
}
It seems to me that the Qt libraray does this all the time.
But I get a "declaration blabla" compiler error. Why is that?
Do I really have to name the method getA()?
I've even tried with Q_PROPERTY:
class Test : public QObject {
Q_OBJECT
Q_PROPERTY(int a READ a WRITE setA)
public:
int a(){return a}
int setA(int val){a=val;}
}
This also does not work.
In Qt itself, the data members are usually in a Private class (the Pimpl idiom), so it's not an issue there.
If you don't use Pimpl (which is a bit tedious and only really necessary if you have to guarantee binary compatibility, or have a very large project where reducing includes has a significant enough effect), the most common way is to prepend the member with a prefix, e.g. m_:
Q_PROPERTY(int a READ a WRITE setA)
public:
void setA( int a ) { m_a = a; }
int a() const { return m_a; }
private:
int m_a;
Another advantage is also that member and local variables are always easy to tell from each other.
Alternatives:
Access the variable via this->a (more tedious than m_a)
Use getA() (makes ugly API, IMHO, but of course depends on your API style - if everything else uses get*, one should just follow suit)

QObject retunrs with exception even after the copy constructor being declared

I am trying to write a sample code for qt script. I thought I am doing the right thing when I declare the QObjecy with the copy construtor and I also took the liberty to declare the = operator. But this code keeps giving me the
'QObject::QObject' : cannot access private member declared in class 'QObject'
Error.
I am declaring a MyClass which is a QObject as follows. I am aware of the fact that this can some one see what I am doing a wroing here.
The header:
#ifndef SCRIPT_CLASSES_H
#define SCRIPT_CLASSES_H
#include "QObject"
#include "QtScript/QScriptValue"
#include "QtScript/QScriptable"
#include "QtScript/QScriptClass"
class MyClass : public QObject
{
Q_OBJECT
// Q_PROPERTY( int _id WRITE setId READ id )
public :
MyClass(QObject *aparent =0) ;
~MyClass();
// bool operator =(MyClass obj);
public slots:
void setId(int d);
int id() const ;
// bool MyClass::equals(const MyClass &other);
private :
int _id;
};
class QScriptEngine;
class Script_Classes : public QObject, public QScriptClass
{
public:
Script_Classes(QScriptEngine *engine);
~Script_Classes();
private :
static QScriptValue myClassToScript(QScriptEngine *engine,const MyClass &in);
static void myClassFromScript(const QScriptValue &object, MyClass &out);
};
#endif // SCRIPT_CLASSES_H
And my source class is as follows:
#include "script_classes.h"
#include "QMetaType"
#include "QtScript/QScriptEngine"
#include "QtScript/QScriptValue"
Q_DECLARE_METATYPE(MyClass)
Q_DECLARE_METATYPE(MyClass*)
MyClass::MyClass(QObject *aparent) : QObject (aparent){}
MyClass::~MyClass(){}
void MyClass::setId(int d){
_id = d;
}
int MyClass::id() const{
return _id;
}
bool MyClass::equals(const MyClass &other)
{
return id() == other.id();
}
bool MyClass::operator =(MyClass obj){
return id()==obj.id();
}
Script_Classes::Script_Classes(QScriptEngine *engine):QObject(engine),QScriptClass(engine)
{
qScriptRegisterMetaType<MyClass>(engine, myClassToScript, myClassFromScript);
MyClass testClass(this);
}
void Script_Classes::myClassFromScript(const QScriptValue &object, MyClass &out){
out.setId(object.property("id").toInt32());
}
QScriptValue Script_Classes::myClassToScript(QScriptEngine *engine, const MyClass &in)
{
QScriptValue value = engine->newObject();
value.setProperty("id", in.id());
return value;
}
The problem is that you cannot copy a QObject. From the QObject documentation:
QObject has neither a copy constructor nor an assignment operator.
This is by design. Actually, they are declared, but in a private
section with the macro Q_DISABLE_COPY(). In fact, all Qt classes
derived from QObject (direct or indirect) use this macro to declare
their copy constructor and assignment operator to be private. The
reasoning is found in the discussion on Identity vs Value on the Qt
Object Model page.
The main consequence is that you should use pointers to QObject (or to
your QObject subclass) where you might otherwise be tempted to use
your QObject subclass as a value. For example, without a copy
constructor, you can't use a subclass of QObject as the value to be
stored in one of the container classes. You must store pointers.
Also QObject has not the == implemented so you cannot compare two instance of your class.
PS What is the point of overloading the = operator and making it operate like the == one? This makes your code obfuscated and debugging much more complex.
EDIT
Assume you have the following simple class inheriting from QObject
class A : public QObject
{
Q_OBJECT
public:
int anInt;
double aDouble;
}
Assume now that you want to create two inctances of A somewhere in your code.
A a1;
A a2;
It is illegal to call a1=a2 since QObject's = operator is not public. What you need to do in order to achieve the copying of the data is to do it manually :
a2.anInt = a1.anInt
a2.aDouble = a1.aDouble
On the other hand if you used pointers it is totally legal to point at the same object
A* a1 = new A;
A* a2 = new A;
a1 = a2;
Now both a1 and a2 point at the same memory location and have the same data. If you want to have two different objects you could create a constructor with argument a pointer to the object. For our simple class you could have:
A::A(A* a)
{
anInt = a->anInt;
aDouble = a->aDouble;
}
and now it is legal do:
A a1;
A a2(&a1);
If you wonder why QObject does not allow assignment read the Identity vs Value part of the Object Model documentation.

Creating a dynamic slot in Qt

I am trying to create slots dynamically and connect them. I am able to dynamically create pushButtons and connect them with existing slots. But what if I have a class with some member functions and I want to use these functions as slots.
From a general perspective, I want to create a template for generating slots given a function pointer. This allows us to create slots without changing the existing code and don't have to recompile using MOC.
If this doesn't make sense let me know. Thank you.
-CV
It does make a lot of sense. I assume QSignalMapper is not what you want. If your functions don't have arguments, maybe something like this is enough:
class SlotForwarder : public QObject
{
Q_OBJECT
public:
typedef void (*Function)(); // or whatever. I never get this syntax right...
SlotForwarder(Function function, QObject* parent = 0)
: QObject(parent)
, m_fptr(function)
{}
public slots:
void forward()
{
m_fptr();
}
private:
Function m_fptr;
};
Create one for each function you want to encapsulate and connect to the forward as usual.
Now, if they do have arguments, maybe this Qt Quarterly article might be of assistance.
Dynamic Signals and Slots by Eskil A. Blomfeldt
The technique involves reimplementing the qt_metacall method yourself. The method has this signature:
int QObject::qt_metacall(QMetaObject::Call call, int id, void **arguments)
Call is the kind of metacall: slot, signal, property read or write, etc. Every slot has an id. The parameters are packed (by value or as pointers) inside the arguments array. Reading the code that the moc generates is a good way to understand how it all works.
Data about raw function signatures is available only during compile time, but slots are resolved at runtime. Because of that mismatch, you will need to wrap the functions into a template adapter type that presents a constant interface to your implementation of qt_metacall and converts the arguments array into something the function can understand (cf. Python unpack operator). Boost.Signals does that kind of template hackery.
A continuation of andref's code so as to use any member function as a slot
class SlotForwarder : public QObject
{
Q_OBJECT
public:
typedef void (*Function)();
SlotForwarder(Function function, QObject* parent = 0)
: QObject(parent)
, m_fptr(function)
{}
public slots:
void forward()
{
m_fptr();
}
private:
Function m_fptr;
};
int main(){
QApplication a(argc, argv);
MyClass myClassObject; //contains a function called MemberFunc
//create a slotforwarder object so
SlotForwarder *memberFuncSlot = new SlotForwarder (std::tr1::bind(&MyClass::MemberFunc, &myClassObject));
QObject::connect(ui.button,SIGNAL(clicked()),memberFuncSlot,SLOT(forward());
}

Resources