Esempio n. 1
0
SmokeObject * SmokeObject::fromPtr(void *ptr, const Class *klass,
                                   bool allocated, bool copy)
{
  if (!klass)
    error("Attempt to create SmokeObject with NULL class");
  if (!ptr)
    error("Attempt to create SmokeObject with NULL pointer");
  SmokeObject *so = instances[ptr];
  if (!so) {
    so = new SmokeObject(ptr, klass, allocated);
#ifdef MEM_DEBUG
    qDebug("%p: created for %p (%s)", so, ptr, klass->name());
#endif
    // record this ASAP, resolveClassId() needs it for virtual callbacks
    if (allocated) // do not record unallocated; not informed when deleted
      instances[so->ptr()] = so;
#ifdef MEM_DEBUG
    else qDebug("%p: unallocated, not registering pointer", so);
#endif
    so->cast(Class::fromSmokeId(so->smoke(), so->module()->resolveClassId(so)));
    /* it seems that all multiple inheritance in Qt goes through
       QObject or QEvent, so we can catch offset pointers at run-time */
    // FIXME: what happens with other libraries? take QtRuby approach?
#ifdef MEM_DEBUG
    if (allocated && so->klass() != klass)
      qDebug("%p: class switch %s::%s -> %s::%s", so,
             klass->smokeBase()->smoke()->moduleName(),
             klass->name(), so->klass()->smokeBase()->smoke()->moduleName(),
             so->klass()->name());
#endif    
    if (so->ptr() != ptr) { // must be multiple inheritance, recache
      SmokeObject *tmp_so = instances[so->ptr()];
#ifdef MEM_DEBUG
      qDebug("%p: multiple inheritance detected, switch to %p", so, so->ptr());
#endif
      if (tmp_so) {
#ifdef MEM_DEBUG
      qDebug("%p: replaced with existing %p", so, tmp_so);
#endif
        delete so;
        so = tmp_so;
        copy = false; // don't think we every want to copy here
      } else instances[so->ptr()] = so;
      instances.remove(ptr);
    }
    if (copy) { // copy the data
      void *tmp_ptr = so->ptr();
      so->_ptr = so->clonePtr(); 
      instances[so->ptr()] = so; // update the instances hash after cloning
      instances.remove(tmp_ptr);
#ifdef MEM_DEBUG
      qDebug("%p: copied to %p", so, so->ptr());
#endif
      so->_allocated = true;
    }
  }
  return so;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/* 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);
}
Esempio n. 4
0
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;
}