-
UID:7394
-
- 注册时间2006-06-03
- 最后登录2024-05-29
- 在线时间9894小时
-
- 发帖5580
- 搜Ta的帖子
- 精华2
- 金钱56167
- 威望5627
- 贡献值20
- 好评度5629
-
访问TA的空间加好友用道具
|
手头上只有dll文件,所以用dumpcpp工具生成了相应的h和cpp文件,可是发现一个问题,自动为dll生成的函数没了返回值,其函数的实现是通过qt_metacall函数改写的,例如 inline void S7ProSim::ReadOutputImage(int StartIndex, int ElementsToRead, S7PROSIMLib::__MIDL___MIDL_itf_S7wspsmx_0000_0002 DataType, QVariant& pData) { void *_a[] = {0, (void*)&StartIndex, (void*)&ElementsToRead, (void*)&DataType, (void*)&pData}; qt_metacall(QMetaObject::InvokeMetaMethod, 24, _a); } 现在我该怎样重新得到返回值呢?变量_a中的第一个元素看起来像是用来保存返回值的,可以通过它得到吗?另外在文档中根本查不到qt_metacall函数的相关信息,有这方面经验的达人能给指点一下吗?
引用第2楼sbtree于2010-01-13 21:01发表的 : dumpcpp工具的主要功能就是利用二进制库文件或者tlb文件生成相关的c++头文件和cpp文件,并利用QAxObject类重新封装了原来的组件,从而简化原来组件的复杂接口,并借此能够利用qt的meta系统,也就能进一步实现信号与槽的功能,与qt完美结合。我现在的问题不在于对com组件系统的了解,诸如IDispatch等接口问题,而是meta,正如上面提到的qt_metacall这样的函数,怎样去认识和应用它,因为文档中没有相关的信息
你的 S7ProSim 是 QAxObject 的派生类吧? 那么就可以考虑看看 QAxObject 的实现了(qaxobject.cpp) - int QAxObject::qt_metacall(QMetaObject::Call call, int id, void **v)
- {
- id = QObject::qt_metacall(call, id, v);
- if (id < 0)
- return id;
- return QAxBase::qt_metacall(call, id, v);
- }
QAxObject 继承自 QObject 和 QAxBase. 对于 QObject::qt_metacall 我们或许不陌生,定义类时添加的 Q_OBJECT 宏就包含其声明,其实现在moc自动生成的 moc_...h 文件内。 对于 QAxBase::qt_metacall ,可以继续看 QAxBase的实现 - int QAxBase::qt_metacall(QMetaObject::Call call, int id, void **v)
- {
- const QMetaObject *mo = metaObject();
- if (isNull() && mo->property(id + mo->propertyOffset()).name() != QByteArray("control")) {
- qWarning("QAxBase::qt_metacall: Object is not initialized, or initialization failed");
- return id;
- }
- switch(call) {
- case QMetaObject::InvokeMetaMethod:
- switch (mo->method(id + mo->methodOffset()).methodType()) {
- case QMetaMethod::Signal:
- QMetaObject::activate(qObject(), mo, id, v);
- id -= mo->methodCount();
- break;
- case QMetaMethod::Method:
- case QMetaMethod::Slot:
- id = internalInvoke(call, id, v);
- break;
- default:
- break;
- }
- break;
- ...
- default:
- break;
- }
- Q_ASSERT(id < 0);
- return id;
- }
慢慢看下去,最后就是COM中熟悉的 IDispach 接口的Invoke函数 - int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v)
- {
- Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
- Q_UNUSED(call);
- // get the IDispatch
- IDispatch *disp = d->dispatch();
- ....
- DISPID dispid = d->metaObject()->dispIDofName(slotname, disp);
- Q_ASSERT(d->metaobj);
- if (dispid == DISPID_UNKNOWN && slotname.toLower().startsWith("set")) {
- // see if we are calling a property set function as a slot
- slotname = slotname.right(slotname.length() - 3);
- dispid = d->metaobj->dispIDofName(slotname, disp);
- isProperty = true;
- }
- if (dispid == DISPID_UNKNOWN)
- return index;
- // slot found, so everthing that goes wrong now should not bother the caller
- index -= mo->methodCount();
- // setup the parame
- DISPPARAMS params;
- DISPID dispidNamed = DISPID_PROPERTYPUT;
- params.cArgs = d->metaobj->numParameter(signature);
- params.cNamedArgs = isProperty ? 1 : 0;
- params.rgdispidNamedArgs = isProperty ? &dispidNamed : 0;
- params.rgvarg = 0;
- VARIANTARG static_rgvarg[QAX_NUM_PARAMS];
- if (params.cArgs) {
- if (params.cArgs <= QAX_NUM_PARAMS)
- params.rgvarg = static_rgvarg;
- else
- params.rgvarg = new VARIANTARG[params.cArgs];
- }
- int p;
- for (p = 0; p < (int)params.cArgs; ++p) {
- bool out;
- QByteArray type = d->metaobj->paramType(signature, p, &out);
- QVariant::Type vt = QVariant::nameToType(type);
- QVariant qvar;
- if (vt != QVariant::UserType)
- qvar = QVariant(vt, v[p + 1]);
- if (!qvar.isValid()) {
- if (type == "IDispatch*")
- qVariantSetValue(qvar, *(IDispatch**)v[p+1]);
- else if (type == "IUnknown*")
- qVariantSetValue(qvar, *(IUnknown**)v[p+1]);
- else if (type == "QVariant")
- qvar = *(QVariant*)v[p + 1];
- else if (mo->indexOfEnumerator(type) != -1)
- qvar = *(int*)v[p + 1];
- else
- qvar = QVariant(QMetaType::type(type), v[p + 1]);
- }
- QVariantToVARIANT(qvar, params.rgvarg[params.cArgs - p - 1], type, out);
- }
- // call the method
- VARIANT ret;
- VariantInit(&ret);
- UINT argerr = 0;
- HRESULT hres = E_FAIL;
- EXCEPINFO excepinfo;
- memset(&excepinfo, 0, sizeof(excepinfo));
- WORD wFlags = isProperty ? DISPATCH_PROPERTYPUT : DISPATCH_METHOD | DISPATCH_PROPERTYGET;
- hres = disp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, wFlags, ¶ms, &ret, &excepinfo, &argerr);
- // get return value
- if (hres == S_OK && ret.vt != VT_EMPTY)
- QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName()), v[0], slot.typeName());
- // update out parameters
- for (p = 0; p < (int)params.cArgs; ++p) {
- bool out;
- QByteArray ptype = d->metaobj->paramType(signature, p, &out);
- if (out)
- QVariantToVoidStar(VARIANTToQVariant(params.rgvarg[params.cArgs - p - 1], ptype), v[p+1], ptype);
- }
- // clean up
- for (p = 0; p < (int)params.cArgs; ++p)
- clearVARIANT(params.rgvarg+p);
- if (params.rgvarg != static_rgvarg)
- delete [] params.rgvarg;
- checkHRESULT(hres, &excepinfo, this, QString::fromLatin1(slotname), params.cArgs-argerr-1);
- return index;
- }
|