0

I need to call a COM function in C++ that returns a reference to a SAFEARRAY(BSTR).

According to this document, it should be:

QAxObject object = new QAxObject(...);
QStringList list;

for(int i=0; i<goodSize; i++)
    list << "10.0";

object->dynamicCall("Frequencies(QStringList&)", list);

for(int i=0; i<list.size(); i++)
    qDebug() << list.at(i);

but the list elements remain to 10.0.

Am I missing something?

EDIT

I used Oleview.exe and actually, the function looks like this: void Frequencies(VARIANT* FrequencyArray);.

But 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).

Maxbester
  • 2,435
  • 7
  • 42
  • 70
  • Returns a `SAFEARRAY`, or returns a reference to a `SAFEARRAY`? COM actually makes that distinction. What does the actual declaration of "Frequencies()" look like in the COM object? – Remy Lebeau Jun 12 '13 at 17:25
  • Returns a reference to a `SAFEARRY`. The prototype is: `Frequencies([in, out] SAFEARRAY(VT_BSTR)*)`. – Maxbester Jun 12 '13 at 19:03
  • Have you tried wrapping your `list` variable in a `QList`/`QVariant`, like the linked doc shows in its `SAFEARRAY` in/out example? The doc says: "Note that the QList the object should fill has to be provided as an element in the parameter list of QVariants." – Remy Lebeau Jun 13 '13 at 00:46
  • Any other idea? The function print is `void Frequencies(VARIANT* FrequencyArray);`. – Maxbester Jun 18 '13 at 12:11
  • That is not what you showed earlier. There is a big difference between passing a pointer to a `SAFEARRAY` and passing a pointer to a `VARIANT`. So what is the actual prototype that `Frequencies()` is really using? – Remy Lebeau Jun 18 '13 at 16:09
  • I'm a bit confused. The documentation says `Use a safearray of strings (VT_BSTR) or reals (VT_R8 for double or VT_R4 for float)` but the hardware seems to show the interface `void Frequencies(VARIANT* FrequencyArray);` (seen through Oleview.exe). In fact, if I pass a QVariant or a QList to Frequencies it returns `Type Mismatch in Parameter. Pass an array of type string or real.`. If I pass a `QStringList` I have no error but the values are not updated. What could I do? I'm out of idea... :( – Maxbester Jun 19 '13 at 06:56
  • I don't use Qt, so I'm out of ideas. I use ActiveX/COM interfaces directly instead, thus don't suffer from these kind of wrapper issues. – Remy Lebeau Jun 19 '13 at 09:49
  • I found someone with the same issue [here](http://www.qtcentre.org/threads/24201-ActiveQt-QVariant-and-VC-VARIANT?p=246220#post_117128). I think I'm going to do it the same way. But it is a pity Qt doesn't allow to do it. – Maxbester Jun 19 '13 at 12:30

2 Answers2

0

The declaration of the COM object's Frequencies() function matches the example in the document, except that the example uses SAFEARRAY(VARIANT) and your COM object uses SAFEARRAY(BSTR) instead. So try adapting the example code for strings, eg:

QList<QString> list;
...
QList<QVariant> parameters;
parameters << QVariant(list);
object->dynamicCall("Frequencies(QList<QString>&)", parameters);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I was thinking to your code. In your example, how do you read the list of strings then? Do you directly read list? Or `for(int i=0; i – Maxbester Jun 22 '13 at 06:54
0

Found the problem. It was the way to read the results. I had to read the first element of parameters then convert it to a QStringList. I am angry against me :(

IBKDataSet *data = function->FunctionData();
int nbFrequencies = data->dynamicCall("GetNumberOfXAxisEntries()").toInt();
QList<QString> frequencies;
for(int i=0; i<nbFrequencies; i++) {
    frequencies << "0.0";
}
QList<QVariant> parameters;
parameters << QVariant(frequencies);
data->dynamicCall("Frequencies(QList<QString>&)", parameters);
frequencies = parameters.first().toStringList();
for(int j=0; j<frequencies.size(); j++) {
    qDebug() << frequencies.at(j);
}
Maxbester
  • 2,435
  • 7
  • 42
  • 70