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; }
SEXP qt_qdataFrameModel(SEXP rparent, SEXP useRoles, SEXP editable) { static Class *dataFrameModelClass = new NameOnlyClass("DataFrameModel", Class::fromName("QAbstractTableModel")); SmokeObject *so = SmokeObject::fromPtr(new DataFrameModel(unwrapSmoke(rparent, QObject), useRoles, editable), Class::fromName("QAbstractTableModel"), true); so->cast(dataFrameModelClass); return so->sexp(); }
SEXP qt_qcast(SEXP x, SEXP klass) { SmokeObject *obj = SmokeObject::fromSexp(x); obj->cast(Class::fromSexp(klass)); return obj->sexp(); }