3

I am developing a C++/Qt application that communicates with an ActiveX server. I try to use a function that returns a reference to an array of floats as a parameter. The function prototype is:

Frequencies([in, out] SAFEARRAY(float)*)

My code is:

QList<QVariant> variantList;
object->dynamicCall("Frequencies(QList<QVariant>&)", variantList);

But unfortunately I have the following error: Type Mismatch in Parameter. Pass an array of type string or real.

After reading this document I also tried QList<QString>& and QList<float>& with no success.

The documentation of the ActiveX server says: Use a safearray of strings (VT_BSTR) or reals (VT_R8 for double or VT_R4 for float).

Any idea?

Thanks!

Maxbester
  • 2,435
  • 7
  • 42
  • 70

3 Answers3

1

http://qt-project.org/doc/qt-4.8/activeqt.html

The ActiveQt modules are part of the Qt Commercial Edition and the Open Source Versions of Qt.

http://qt-project.org/doc/qt-4.8/qaxobject.html#details

http://qt-project.org/doc/qt-4.8/qaxbase.html#details

Here is a quote from the documentation for QAXBase:

To call the methods of a COM interface described by the following IDL

dispinterface IControl
{
properties:
    [id(1)] BSTR text;
    [id(2)] IFontDisp *font;

methods:
    [id(6)] void showColumn([in] int i);
    [id(3)] bool addColumn([in] BSTR t);
    [id(4)] int fillList([in, out] SAFEARRAY(VARIANT) *list);
    [id(5)] IDispatch *item([in] int i);
};

use the QAxBase API like this:

QAxObject object("<CLSID>");

QString text = object.property("text").toString();
object.setProperty("font", QFont("Times New Roman", 12));

connect(this, SIGNAL(clicked(int)), &object, SLOT(showColumn(int)));
bool ok = object.dynamicCall("addColumn(const QString&)", "Column 1").toBool();

QList<QVariant> varlist;
QList<QVariant> parameters;
parameters << QVariant(varlist);
int n = object.dynamicCall("fillList(QList<QVariant>&)", parameters).toInt();

QAxObject *item = object.querySubItem("item(int)", 5);

Note that the QList the object should fill has to be provided as an element in the parameter list of QVariants.

So basically you need to make sure that you are nesting a QList, in order to make your SAFEARRAY work.

Hope that helps.

phyatt
  • 18,472
  • 5
  • 61
  • 80
  • Nope... Still have the same error message. I tried with a QStringList: `QStringList list; object->dynamicCall("Frequencies(QStringList&)", list);`. Like this I have an error that tells me the array doesn't have the good size. So I added elements in it: `for(int i=0; i – Maxbester Jun 05 '13 at 15:18
  • So to nest it, you need to have: `QStringList stringlist; QList variantList; variantList << QVariant(stringlist);` It looks like if you don't nest it, it doesn't work out. Then you call `object.dynamicCall("Frequencies(QList&)", variantList);` or maybe `object.dynamicCall("Frequencies(QList&)", variantList);` – phyatt Jun 05 '13 at 15:54
  • I don't understand why it is necessary to nest it. There are two `dynamicCall()` functions. The first one: [`QVariant QAxBase::dynamicCall ( const char * function, const QVariant & var1 = QVariant()...)`](http://qt-project.org/doc/qt-4.8/qaxbase.html#dynamicCall) only needs one argument which may not be a list. The second one: [`QVariant QAxBase::dynamicCall ( const char * function, QList & vars )`](http://qt-project.org/doc/qt-4.8/qaxbase.html#dynamicCall-2) requires a list indeed. Why couldn't I use the first one passing a QStringList? – Maxbester Jun 05 '13 at 16:05
  • Because of the note in the documentation. `Note that the QList the object should fill has to be provided as an element in the parameter list of QVariants.` This structure is how the docs show it being passed. – phyatt Jun 05 '13 at 17:09
  • So your advice is to write: `QStringList list; for(int i=0; i parameters; parameters << QVariant(list); object->dynamicCall("Frequencies(QList&)", parameters); for(int i=0; idynamicCall("Frequencies(QList&)", parameters);` or `object->dynamicCall("Frequencies(QStringList&)", parameters);`? – Maxbester Jun 07 '13 at 06:37
  • I'm all out of ideas... None of the above mentioned propositions worked. I tried `object->dynamicCall("Frequencies(QList&)", parameters);`, `object->dynamicCall("Frequencies(QStringList&)", parameters);` and `object->dynamicCall("Frequencies(QList&)", parameters);`. The two last ones didn't return an error message but the values weren't updated. – Maxbester Jun 12 '13 at 16:20
  • Did you try `object->dynamicCall("Frequencies(QList&)", parameters);` (note the Q in front of Variant). If the Qt solution isn't working for this ActiveX server, then finding a non-Qt c++ solution is the answer. :( Sorry that the qt docs didn't help. – phyatt Jun 12 '13 at 17:02
  • I've tried with the QVariant actually (just forgot it when typing). Thanks for your help anyway. How would do it without Qt? I mean in pure C++? – Maxbester Jun 12 '13 at 19:04
  • This is the best I've got: https://www.google.com/search?q=safearray+c%2B%2B . Good luck. – phyatt Jun 12 '13 at 19:08
0

The Qt example doesn't show how to read the results. It was my problem...

QList<QString> values;
for(int i=0; i<nbFrequencies; i++) {
    values << "0.0";
}
QList<QVariant> variantList;
parameters << QVariant(values);
object->dynamicCall("Frequencies(QList<QString>&)", variantList);

values = variantList.first().toStringList();

for(int j=0; j<values.size(); j++) {
    qDebug() << values.at(j);
}

It is necessary to read the first element of variantList and to convert it to a QStringList. Very simply...

Maxbester
  • 2,435
  • 7
  • 42
  • 70
0

QT on avtivex works not so good.It just use IDispatch interface to invoke the method or property. With an activex control,you can import MFC library then use COleDispatchDriver's InvokeHelper member to invoke the method.just like this:

IDispatch* map_itf = NULL;
map_ctrl_->queryInterface(IID_IDispatch,(void**)&map_itf);

if(map_itf)
{
    COleDispatchDriver driver(map_itf,FALSE);

    static BYTE parms[] =
        VTS_PR4 VTS_PR4 VTS_PR8 VTS_PR8 VTS_I2;

    driver.InvokeHelper(0x22, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
        &screen_x, &screen_y, &map_x, &map_y, miScreenToMap);
}

Enjoy QT,it's a great project