void marshal_from_sexp<SmokeClassWrapper>(MethodCall *m) { SEXP v = m->sexp(); SmokeType type = m->type(); SmokeObject *o = NULL /*, *coerced = NULL */; /* Not clear if we want to (partially) support this complicated C++ feature if (v != R_NilValue) { o = SmokeObject::fromSexp(v); if (!o->instanceOf(type.className())) { // attempt implicit conversion coerced = o->convertImplicitly(type); if (coerced) o = coerced; else error("Failed to coerce an instance of type '%s' to '%s'", o->className(), type.className()); } } */ o = from_sexp<SmokeObject *>(v, type); void *ptr = o ? o->castPtr(type.className(), m->returning() && !type.fitsStack()) : NULL; setItemValue(m, ptr); /* m->marshal(); if (coerced) delete coerced; */ return; }
void *_unwrapSmoke(SEXP x, const char *type) { void *ans = NULL; if (!isNull(x)) { SmokeObject *so = SmokeObject::fromSexp(x); if (so) ans = so->castPtr(type); } return ans; }
extern "C" SEXP qt_qmetaInvoke(SEXP x, SEXP s_id, SEXP s_args) { SmokeObject *so = SmokeObject::fromSexp(x); int id = from_sexp<int>(s_id); QObject * qobj = reinterpret_cast<QObject *>(so->castPtr("QObject")); MocMethod method(so->smoke(), qobj->metaObject(), id); SEXP ret = method.invoke(x, s_args); if (method.lastError() > Method::NoError) error("Meta method invocation failed for: '%s::%s'", so->klass()->name(), method.name()); return ret; }
/* We catch all qt_metacall invocations */ extern "C" SEXP qt_qmetacall(SEXP x, SEXP s_call, SEXP s_id, SEXP s_args) { SmokeObject *so = SmokeObject::fromSexp(x); QMetaObject::Call call = enum_from_sexp<QMetaObject::Call>(s_call, SmokeType()); int id = from_sexp<int>(s_id); void **args = reinterpret_cast<void **>(from_sexp<void *>(s_args)); // Assume the target slot is a C++ one Smoke::StackItem i[4]; i[1].s_enum = call; i[2].s_int = id; i[3].s_voidp = args; so->invokeMethod("qt_metacall$$?", i); int ret = i[0].s_int; if (ret < 0) { return ScalarInteger(ret); } if (call != QMetaObject::InvokeMetaMethod) return ScalarInteger(id); QObject * qobj = reinterpret_cast<QObject *>(so->castPtr("QObject")); // get obj metaobject with a virtual call const QMetaObject *metaobject = qobj->metaObject(); // get method count int count = metaobject->methodCount(); QMetaMethod method = metaobject->method(id); if (method.methodType() == QMetaMethod::Signal) { // FIXME: this override of 'activate' is obsolete metaobject->activate(qobj, id, (void**) args); return ScalarInteger(id - count); } DynamicBinding binding(MocMethod(so->smoke(), metaobject, id)); QVector<SmokeType> stackTypes = binding.types(); MocStack mocStack = MocStack(args, stackTypes.size()); SmokeStack smokeStack = mocStack.toSmoke(stackTypes); binding.invoke(so, smokeStack.items()); mocStack.returnFromSmoke(smokeStack, stackTypes[0]); if (binding.lastError() == Method::NoError) warning("Slot invocation failed for %s::%s", so->klass()->name(), binding.name()); return ScalarInteger(id - count); }
Method* MocClass::findMethod(const MethodCall& call) const { Method *method = _delegate->findMethod(call); if (method) return(method); SmokeObject *o = call.target(); /* only QObjects have meta methods */ if (o && o->ptr() && o->instanceOf("QObject") && o->klass() == this) { /* unwrap the call */ QObject * qobject = reinterpret_cast<QObject *>(o->castPtr("QObject")); const QMetaObject * meta = qobject->metaObject(); /* get the method id */ int id = findMethodId(o->smoke(), meta, call.method()->name(), call.args()); if (id >= 0) method = new MocMethod(o->smoke(), meta, id); } return method; }
QVariant qvariant_from_sexp(SEXP rvalue, int index) { QVariant variant; if (index == -1) { /* If a particular element is not selected, then non-lists of length one are considered scalars. Otherwise, collections. Except for raw vectors, which are naturally QByteArrays. */ if (TYPEOF(rvalue) == RAWSXP) return QVariant(from_sexp<QByteArray>(rvalue)); else if (TYPEOF(rvalue) == VECSXP || length(rvalue) > 1) { SEXP rlist = coerceVector(rvalue, VECSXP); if (getAttrib(rvalue, R_NamesSymbol) != R_NilValue) variant = asQVariantOfType(rlist, QMetaType::QVariantMap); else variant = asQVariantOfType(rlist, QMetaType::QVariantList); return variant; } index = 0; } switch(TYPEOF(rvalue)) { case RAWSXP: variant = qVariantFromValue(RAW(rvalue)[index]); break; case LGLSXP: // Rprintf("Logical\n"); // FIXME: by converting to 'bool' all NA become TRUE variant = QVariant((bool)LOGICAL(rvalue)[index]); break; case REALSXP: // Rprintf("Real\n"); variant = QVariant(REAL(rvalue)[index]); break; case INTSXP: // Rprintf("Integer\n"); { SEXP levels; if ((levels = getAttrib(rvalue, R_LevelsSymbol)) != R_NilValue) { int level = INTEGER(rvalue)[index]; SEXP level_str = NA_STRING; /*Rprintf("getting level: %d\n", level);*/ if (level != NA_INTEGER) level_str = STRING_ELT(levels, level - 1); variant = QVariant(sexp2qstring(level_str)); } else variant = QVariant(INTEGER(rvalue)[index]); break; } case STRSXP: // Rprintf("String\n"); variant = QVariant(sexp2qstring(STRING_ELT(rvalue, index))); break; case EXTPTRSXP: // Rprintf("External pointer\n"); variant = qVariantFromValue(unwrapPointer(rvalue, void)); break; case VECSXP: variant = from_sexp<QVariant>(VECTOR_ELT(rvalue, index)); break; case ENVSXP: { SmokeObject *so = SmokeObject::fromSexp(rvalue); if (so->instanceOf("QWidget")) variant = qVariantFromValue(reinterpret_cast<QWidget *>(so->castPtr("QWidget"))); else if (so->instanceOf("QObject")) variant = qVariantFromValue(reinterpret_cast<QObject *>(so->castPtr("QObject"))); else { QMetaType::Type type = (QMetaType::Type) QMetaType::type(so->className()); if (type) variant = asQVariantOfType(rvalue, type, false); else variant = qVariantFromValue(so->ptr()); } } break; case NILSXP: // invalid QVariant break; default: error("Converting to QVariant: unhandled R type"); } return variant; }