PDA

View Full Version : dynamicCall with [in, out] SAFEARRAY(VARIANT_BOOL)* parameter



kenpanda
4th July 2012, 11:51
Hi to all,

I have to access a COM component method having this signature :


HRESULT SetBillValueEnables([in, out] SAFEARRAY(VARIANT_BOOL)* billValueEnables);


I used the dumpcpp tool to import the type lib header, and according to
http://qt-project.org/doc/qt-4.8/qaxbase.html

I tried this


QList<QVariant> billValuesToDevice;
billValuesToDevice << false << false << false << false << false;
QList<QVariant> parameters;
parameters << billValuesToDevice;
_acc->dynamicCall("SetBillValueEnables(QList<QVariant>*&)",parameters);


But as result, I receive the error message :
QAxBase: Error calling IDispatch member SetBillValueEnables: Unknown error

I first thought that the issue was caused by the COM implementation of the API, so I give it a try with Visual C++, and there it works fine with :


SAFEARRAYBOUND bounds;
bounds.cElements = 5;
bounds.lLbound = 0;
SAFEARRAY *pNewValues;
pNewValues = SafeArrayCreate(VT_BOOL,1,&bounds);
short output[5];
for (long i=0; i<5; i++)
{
output[i] = true;
SafeArrayPutElement(pNewValues,&i,&(output[i]));
output[i] = false;
}

_pAcceptor->SetBillValueEnables(&pNewValues);

Can someone please help me with this, or confirm that SAFEARRAY(VARIANT_BOOL)* is not a supported parameter type ?

d_stranz
4th July 2012, 22:24
_acc->dynamicCall("SetBillValueEnables(QList<QVariant>*&)",parameters);

Maybe your function declaration is incorrect. Try this:


_acc->dynamicCall("SetBillValueEnables(QList<QVariant>&)",parameters);

(Note, no "*" - it is QList<QVariant>& ).

kenpanda
5th July 2012, 15:23
I already tried this, but it gives the same error.
Moreover the signature (QList<QVariant>*&) is coming from the header generated by the Qt dumpcpp tool.
I attached the generated header to this post.
Is it possible that there is a bug in this dumpcpp ?

d_stranz
5th July 2012, 21:11
Ah, one other thing: your COM version is different from your Qt version in that you are using a "short" to represent the VT_BOOL arguments in the COM version (which is correct), whereas in Qt you are using a QVariant::Bool type, which probably is 8 bits or less. VT_BOOL is required to be a 16-bit type. In addition, VT_TRUE is defined as 0xFFFF and VT_FALSE as 0x0000. Simply setting the value to C++ "true" is probably incorrect.

kenpanda
6th July 2012, 08:20
I know but according the Qt doc, the matching type for VARIANT_BOOL is bool or bool& (depending if [in] or [in|out] parameter)

Anyway, I changed my test code to this, and I have the same results :crying:


QList<QVariant> billValuesToDevice;
billValuesToDevice << 0x0000 << 0xFFFF << 0x0000 << 0xFFFF << 0x0000;
QList<QVariant> parameters;
parameters << billValuesToDevice;
_acc->dynamicCall("SetBillValueEnables(QList<QVariant>*&)",parameters);

d_stranz
7th July 2012, 02:05
billValuesToDevice << 0x0000 << 0xFFFF << 0x0000 << 0xFFFF << 0x0000;

This doesn't mean that your QVariant item contains a "short" (16-bit) integer. Have you looked at the QVariant type to see what it actually contains?

Have you tried calling one of the COM methods that uses some kind of variable other than VT_BOOL? Like a BSTR (which maps to a QString)? Do those kinds of calls work?

Do you even know if "_acc" is actually pointing to a COM object instance of the type you think?


QAxBase: Error calling IDispatch member SetBillValueEnables: Unknown error
What is the actual error code returned here?

Do you know that "SetBillValueEnables" is actually the string you need to pass to dynamicCall()? No "_" or something like that required in front of the name? No namespace that you're leaving out?

Does your COM object allow you to call that method at the time you are calling it (i.e. is there some series of prerequisite methods that must be called first in order to put the object into the right state for this call to work?)

Everything you are trying is based on the assumption that there is something wrong with the arguments, but it could be something entirely different from that. If you can get a COM method with a different type of argument to work on the same object instance, then you can start to narrow it down to a specific problem.

Edit:


I know but according the Qt doc, the matching type for VARIANT_BOOL is bool or bool& (depending if [in] or [in|out] parameter)

Oops, sorry, missed this before I wrote all that above. So the parameters probably -are- correct, so you are likely calling the method at the wrong time.

I've just looked at your nmpost.h file. All of the COM classes in there are inherited from QAxObject. You should be able to call the class methods directly - no need for "dynamicCall()".

So assuming that "_acc" is a pointer to an instance of IAcceptor_API, then why don't you simply do this?


_acc->SetBillValueEnables( &parameters );

(Another observation: why do you make a copy of your QList< QVariant > in "parameters" after you fill the original with values? Why not just pass the original?)

kenpanda
15th July 2012, 08:04
Sorry d_stranz,
I'm currently on holliday, but basically :
- I do not call SetBillValueEnables because it is not recommended to call it directly. Instead this method is in fact a slot and should be called via a signal. Despite, I already tried this, but it does not work neither.
- _acc is indeed a pointer to IAcceptor_API
- I made a copy to "parameters", the way it is described in the QAxObject description (look for the example to call 'fillList');
in fact there are multiple overload of dynamicCall, each of them with a different number of QVariant parameter (1->8), and a last one with a QVariantList.
As the first parameter a need to give IS a list of bool, I try to give this array of bool as the first item of the QVariantList.

I already tried to give use the overload to give the booleans via the overload, no luck:crying:


Thanks for your help, and sorry again for this late reply

amleto
15th July 2012, 11:34
"I do not call SetBillValueEnables because it is not recommended to call it directly. Instead this method is in fact a slot and should be called via a signal"
Don't know where you read that - any slot can be called like a normal member method (after all, that is all that it is).

kenpanda
16th July 2012, 07:27
Don't know where you read that - any slot can be called like a normal member method (after all, that is all that it is).

I read this from the documentation generated via the QAxObject :


QString result = _acc->generateDocumentation();

:



void SetBillValueEnables (QVariantList*& billValueEnables) [slot]
Connect a signal to this slot:
QObject::connect(sender, SIGNAL(someSignal(QVariantList*&)), object, SLOT(SetBillValueEnables(QVariantList*&)));
Or call the function directly:
QVariantList params = ...
object->dynamicCall("SetBillValueEnables(QVariantList*&)", params);

Maxbester
4th June 2013, 11:52
Hi,

I am facing a similar problem. Did you solve this one? How?

Thanks