История изменений
Исправление
ckotinko,
(текущая версия)
:
я тебя даже пожалел и написал тебе как можно сделать
много таких:
template<T1,T2...>
bool call(QObject * obj, char * method, const T1& t1, const T2& t2...) {
//N = number of arguments
QMetaMethod m = obj->metaObject()->methodIndex(method);
if (!m.isValid() || m.argumentCount() != N) {
//shit!
return false;
}
int types[N] = {
qMetaTypeId<T1>(),
qMetaTypeId<T2>(),
...
};
const void ** args[N] = {
&t1,
&t2,
...
};
return do_really_call(obj, m, N, types, data);
}
static void do_clean_up(const QByteArray& data, int n) {
Q_ASSERT(data.size() >= n * (sizeof(void*)*3);
void ** hptr = (void**)data.data();
for(int i = 0; i < n; ++i) {
int t = PTR_TO_INT(hptr[2]);
QMetaType::destruct(t, hptr[1]);
hptr+=3;
}
}
static bool do_really_call(QObject * obj, const QMetaMethod& m, int n, int ** const types, const void ** data)
{
int hdr_size = round_up_to_16(sizeof(void*)*3*n);
int data_size = hdr_size;
int offsets[n];//больше 10 аргументов все равно не поддерживают
int dtypes[n];
const char * names[n];
for(int i = 0; i < n; ++i) {
int pt = m.parameterType(i);
if (pt != types[i]) {
if (!QMetaType::hasRegisteredConvertedFunction(types[i], pt)) {
return false;
}
}
offsets[i] = data_size;
dtypes[i] = pt;
names[i] = QMetaType::typeName(pt);
data_size += align_up_to_16(QMetaType::sizeOf(pt));
}
QByteArray data;
data.resize(data_size);
void ** hptr = (void**)data.data();
void * wptr = (void*)(data.data()+hdr_size);
int J = 0;
bool ok = true;
for(J = 0; J < n; ++J) {
*hptr = names[J];
++hptr;
*hptr = wptr+offsets[J];
++hptr;
*hptr = INT_TO_PTR(dtypes[J]);
++hptr;
if (types[J] == dtypes[J])
QMetaType::construct(types[J], wptr+offsets[J], data[J]);
else
ok = QMetaType::convert(data[J], types[J], wptr+offsets[J], dtypes[J]);
if (!ok) break;
}
if (!ok) {
do_clean_up(data, J);
return false;
}
m.invoke(obj, Qt::QueuedConnection, "really_really_call", m.index(), n, data);
return true;
}
//Q_INVOKABLE
void MyObject::really_really_call(int mi, int n, const QByteArray& args) {
QMetaMethod m = metaObject()->method(mi);
void ** hptr = (void**)args.data();
//check for errors
switch(n) {
...
case 4:
m.invoke(this, Qt::DirectConnection,
QGenericArgument(hptr[0*3], hptr[0*3+1]),
QGenericArgument(hptr[1*3], hptr[1*3+1]),
QGenericArgument(hptr[2*3], hptr[2*3+1]),
QGenericArgument(hptr[3*3], hptr[3*3+1]));
break;
}
do_clean_up(n, args);
}
Исправление
ckotinko,
:
я тебя даже пожалел и написал тебе как можно сделать
много таких:
template<T1,T2...>
bool call(QObject * obj, char * method, const T1& t1, const T2& t2...) {
//N = number of arguments
QMetaMethod m = obj->metaObject()->methodIndex(method);
if (!m.isValid() || m.argumentCount() != N) {
//shit!
return false;
}
int types[N] = {
qMetaTypeId<T1>(),
qMetaTypeId<T2>(),
...
};
const void ** args[N] = {
&t1,
&t2,
...
};
return do_really_call(obj, m, N, types, data);
}
static void do_clean_up(const QByteArray& data, int n) {
Q_ASSERT(data.size() >= n * (sizeof(void*)*3);
void ** hptr = (void**)data.data();
for(int i = 0; i < n; ++i) {
int t = PTR_TO_INT(hptr[2]);
QMetaType::destruct(t, hptr[1]);
hptr+=3;
}
}
static bool do_really_call(QObject * obj, const QMetaMethod& m, int n, int ** const types, const void ** data)
{
int hdr_size = round_up_to_16(sizeof(void*)*3*n);
int data_size = hdr_size;
int offsets[n];//больше 10 аргументов все равно не поддерживают
int dtypes[n];
const char * names[n];
for(int i = 0; i < n; ++i) {
int pt = m.parameterType(i);
if (pt != types[i]) {
if (!QMetaType::hasRegisteredConvertedFunction(types[i], pt)) {
return false;
}
}
offsets[i] = data_size;
dtypes[i] = pt;
names[i] = QMetaType::typeName(pt);
data_size += align_up_to_16(QMetaType::sizeOf(pt));
}
QByteArray data;
data.resize(data_size);
void ** hptr = (void**)data.data();
void * wptr = (void*)(data.data()+hdr_size);
int J = 0;
bool ok = true;
for(J = 0; J < n; ++J) {
*hptr = names[J];
++hptr;
*hptr = wptr+offsets[J];
++hptr;
*hptr = INT_TO_PTR(dtypes[J]);
++hptr;
if (types[J] == dtypes[J])
QMetaType::construct(types[J], wptr+offsets[J], data[J]);
else
ok = QMetaType::convert(data[J], types[J], wptr+offsets[J], dtypes[J]);
if (!ok) break;
}
if (!ok) {
do_clean_up(data, J);
return false;
}
m.invoke(obj, Qt::QueuedConnection, "really_really_call", m.index(), n, data);
return true;
}
//Q_INVOKABLE
void MyObject::really_really_call(int mi, int n, const QByteArray& args) {
QMetaMethod m = metaObject()->method(mi);
void ** hptr = (void**)args.data();
//check for errors
switch(n) {
...
case 4:
m.invoke(this, Qt::DirectConnection,
QGenericArgument(hptr[0*3], hptr[0*3+2]),
QGenericArgument(hptr[1*3], hptr[1*3+2]),
QGenericArgument(hptr[2*3], hptr[2*3+2]),
QGenericArgument(hptr[3*3], hptr[3*3+2]));
break;
}
do_clean_up(n, args);
}
Исходная версия
ckotinko,
:
я тебя даже пожалел и написал тебе как можно сделать
много таких:
template<T1,T2...>
bool call(QObject * obj, char * method, const T1& t1, const T2& t2...) {
//N = number of arguments
QMetaMethod m = obj->metaObject()->methodIndex(method);
if (!m.isValid() || m.argumentCount() != N) {
//shit!
return false;
}
int types[N] = {
qMetaTypeId<T1>(),
qMetaTypeId<T2>(),
...
};
const void ** args[N] = {
&t1,
&t2,
...
};
return do_really_call(obj, m, N, types, data);
}
static void do_clean_up(const QByteArray& data, int n) {
Q_ASSERT(data.size() >= n * (sizeof(void*)*3);
void ** hptr = (void**)data.data();
for(int i = 0; i < n; ++i) {
int t = PTR_TO_INT(hptr[2]);
QMetaType::destruct(t, hptr[1]);
hptr+=3;
}
}
static bool do_really_call(QObject * obj, const QMetaMethod& m, int n, int ** const types, const void ** data)
{
int hdr_size = round_up_to_16(sizeof(void*)*3*n);
int data_size = hdr_size;
int offsets[n];//больше 10 аргументов все равно не поддерживают
int dtypes[n];
const char * names[n];
for(int i = 0; i < n; ++i) {
int pt = m.parameterType(i);
if (pt != types[i]) {
if (!QMetaType::hasRegisteredConvertedFunction(types[i], pt)) {
return false;
}
}
offsets[i] = data_size;
dtypes[i] = pt;
names[i] = QMetaType::typeName(pt);
data_size += align_up_to_16(QMetaType::sizeOf(pt));
}
QByteArray data;
data.resize(data_size);
void ** hptr = (void**)data.data();
void * wptr = (void*)(data.data()+hdr_size);
int J = 0;
bool ok = true;
for(J = 0; J < n; ++J) {
*hptr = names[J];
++hptr;
*hptr = wptr;
++hptr;
*hptr = INT_TO_PTR(dtypes[J]);
++hptr;
if (types[J] == dtypes[J])
QMetaType::construct(types[J], wptr, data[J]);
else
ok = QMetaType::convert(data[J], types[J], wptr, dtypes[J]);
if (!ok) break;
}
if (!ok) {
do_clean_up(data, J);
return false;
}
m.invoke(obj, Qt::QueuedConnection, "really_really_call", m.index(), n, data);
return true;
}
//Q_INVOKABLE
void MyObject::really_really_call(int mi, int n, const QByteArray& args) {
QMetaMethod m = metaObject()->method(mi);
void ** hptr = (void**)args.data();
//check for errors
switch(n) {
...
case 4:
m.invoke(this, Qt::DirectConnection,
QGenericArgument(hptr[0*3], hptr[0*3+2]),
QGenericArgument(hptr[1*3], hptr[1*3+2]),
QGenericArgument(hptr[2*3], hptr[2*3+2]),
QGenericArgument(hptr[3*3], hptr[3*3+2]));
break;
}
do_clean_up(n, args);
}