Оказалось все довольно просто: есть список имён методов (обычные строки, представляете?

Перед вызовом "метасистема" ищет нужный индекс по сигнатуре метода: methodName(argType0,argtype1,argType2),
а потом просто обращается к статической функции для вызова, в которую передаются указатель на объект, индекс функции и набор аргументов.
А в этой статической функции!!! Бугагашеньки

- Код:
static_metacall(object, index, params) {
PQObject *_t = static_cast<PQObject *>(object);
switch (_id) {
case 0: _t->setObjectName((*reinterpret_cast< QString(*)>(_a[1]))); break;
case 1: { QVariant _r = _t->getUserProperty((*reinterpret_cast< const QString(*)>(_a[1])));
if (_a[0]) *reinterpret_cast< QVariant*>(_a[0]) = _r; } break;
case 2: { QString _r = _t->objectName();
if (_a[0]) *reinterpret_cast< QString*>(_a[0]) = _r; } break;
/* и так далее весь список методов QObject */
}
Так вот к чему я все это :) есть мысль создать свою метасистему поверх существующей. Таким образом можно будет:
- во первых: избавится от обёрток для методов (от обёрток для классов избавится все-же не получится);
- во вторых: избавится от проблем с кастованием типов;
- в третьих: значительно ускорить вызовы методов;
- в четвертых: значительно упростить создание обёрток, фактически все сведётся только к описанию всех методов в заголовочном файле, создавать тела методов уже будет не нужно.
Почему бы не использовать существующую метасистему?
В настоящей реализации она и используется. Но оригинальные классы Qt имеют очень, не побоюсь этого слова, скудную мета-информацию, и предоставляют доступ метасистеме только к наиболее востребованным методам. Для того чтобы открыть доступ ко всем методам, необходимо создавать обёртку и переопределять все методы, устанавливая им флаг "виден для метасистемы".
При этом для вызова конкретного метода необходимо подготовить набор аргументов к их передачи: т.е. нужно произвести их проверку, произвести возможные преобразования и только потом отправить в вызов. В собственной реализации этот момент можно будет обыграть заранее, упростив его до минимума.
Как я вижу реализацию метасистемы PHPQt5?
Вся магия будет в макросах, т.е. минимум кода. Не нужно будет самостоятельно составлять функцию со списком методов, нужно будет просто перечислить методы в макросах, а макросы, распаковавшись прекомпилятором, создадут валидные тела функций.
К примеру, я хочу создать обертку для QTimer:
- Код:
class PQTimer : public QTimer
{
Q_OBJECT // инициализация местасистемы Qt
PQ_OBJECT // инициализация местасистемы PHPQt5
// #define PQ_METHOD(returnType, methodName, paramType1)
PQ_META_METHODS_START { // распакуется в
pq_static_metacall(QObject *object, int methodIndex, void **params) {
PQTimer *pobject = static_cast<PQTimer *>(object);
switch(methodIndex) {
PQ_METHOD_1(void, setInterval, int); // распакуется в
0: pobject->setInterval( (*reinterpret_cast<int>(params[0])) );
PQ_METHOD_0(void, start); // распакуется в
1: pobject->start();
} PQ_META_METHODS_END // распакуется в
}}
}
Таким образом движку останется лишь найти нужный индекс метода и вызвать функцию pq_static_metacall со всеми аргументами, которые даже кастовать не придётся - они будут передаваться как есть, за исключением случаев с автоприведением int-bool-string-double.
Буду развивать эту идею, попутно экспериментировать. Возможно в будущем движок приобретёт новый облик :)
п.с. на стороне php ничего не изменится.