1

I'm very new to PyQt5. I'm now trying to call ocx function which takes VARIANT* type as argument. So I created QVariant variable and toss it into the function, but I can get nothing but only error.

The function prototype is:

LONG ReceiveProcDataArr(LONG nRqID, BSTR sProc, LONG nOutRecIndex, VARIANT* pArrData)

and i tried to use this with following code:

from PyQt5.QtCore import QVariant
ocx_module = QAxWidget("[ocx control]")

# some codes to skip...

data = QVariant()
item_length = ocx_module.dynamicCall("ReceiveProcDataArr(int, QString, int, QVariant&)", [rqID, proc, 0, data])

and I got error:

Error calling IDispatch member ReceiveProcDataArr: Type mismatch in parameter 3

I can use "ocx_module" which does not take argument or takes only int/string type such as:

success = ocx_module.dynamicCall("Init()")
success = ocx_module.dynamicCall("Login(QString, QString)", user_id, user_pw)

My environment is:

  • windows 10 pro
  • python 3.6 x86
  • pyqt5 == 5.9

I searched for a while, but I cannot find answer about this. Can anyone help me?

ulismoon
  • 61
  • 6
  • If you weren't trying to interface with PyQt, what would the signature for `ReceiveProcDataArr` actually be? I ask because PyQt5 `QVariant` support is different to PyQt4 and it's not clear to me that you actually should be using `QVariant` (see [docs](http://pyqt.sourceforge.net/Docs/PyQt5/pyqt_qvariant.html)). Unfortunately I can't find any information on what your trying to do, so it's a bit hard for me to get any further than this. – three_pineapples Apr 02 '18 at 10:48
  • I think you need to keep a separate list for the params (because it will be modified by the osx function). Then each element in that list must be a `QVariant` having the right type. The params are then passed as the second argument to `dynamicCall`. The `VARIANT* pArrData` seems to be a pointer to an array. So maybe `params = [QVariant(rqID), QVariant(proc), QVariant(0), QVariant([])]` will work. Then you can do `data = params[3]` after the call to get the array data. – ekhumoro Apr 02 '18 at 18:57
  • @ekhumoro I tried what you suggested, but the result was same as I got before. Thanks for your opinion anyway. – ulismoon Apr 03 '18 at 00:57
  • @three_pineapples At first, I loaded ocx module in Visual Studio 2017 C++ project (with class wizard - MFC class from ActiveX control) and I found function definition starts with `long ReceiveProcDataArr(long nRqID, LPCTSTR sProc, long nOutRecIndex, VARIANT * arrData)`. This function gets data from server and they do not returns data directly, fill data in passed `arrData`. I'm C++ dummy, so I decided to use PyQt to use ocx in python. Because original param type was `VARIANT*`, I assumed `QVariant` is right one. This is whole story. – ulismoon Apr 03 '18 at 02:01
  • Not sure I'm going to be much further help here. I did find [this](https://stackoverflow.com/questions/17595606/how-to-use-variant-with-dynamiccall) where someone had trouble with `VARIANT*` parameters in Qt and they gave up. My final suggestions (that are probably unhelpful) would be to a) try random data types (even Python ones like list, etc) and b) trying to construct a simple Qt C++ example to see if you can narrow it down to either a Qt or PyQt issue. – three_pineapples Apr 03 '18 at 07:46
  • The in and out parameters clearly ***must*** be `QVariant&`, so your only possiblilities are the [types specified here](https://doc.qt.io/qt-5/qvariant-obsolete.html#Type-enum). If none of those work, I don't think there is anything else you can do. I suppose `QVariant(QVariant.StringList)` is the best bet if `VARIANT*` is an array of `BSTR`. If it's not, you really need to find out the *precise* type of data that the function is supposed to return through that last parameter. – ekhumoro Apr 03 '18 at 18:40
  • PS: found this [old bug report](https://bugreports.qt.io/browse/QTBUG-22394), which looks very similar. Unfortunately, it got no replies. There are also many unresolved threads on various forums asking how to handle `VARIANT*`. So the prognosis doesn't look good... – ekhumoro Apr 03 '18 at 18:57
  • @ekhumoro Thanks for all your efforts. I'll try several things and leave comment if I find any breakthrough. – ulismoon Apr 04 '18 at 00:43
  • @three_pineapples That article you linked is such a bad news... Thanks for your help. I'll try things by myself from now. – ulismoon Apr 04 '18 at 00:46
  • Do you see my answer? – Davide Pizzolato Sep 19 '18 at 13:38

1 Answers1

0

This works for me:

list1 = ["VW SPL", 0]
print(ocx.dynamicCall('ReadVariable(QVariant, QVariant&)', list1))
print(list1)

In your case try this:

data = [rqID, proc, 0, 0]
item_length = ocx_module.dynamicCall("ReceiveProcDataArr(QVariant, QVariant, 
QVariant, QVariant&)", data)
print(data[3])

Beware that the reference only updates the list:

int foo = 0
data = [rqID, proc, 0, foo]
item_length = ocx_module.dynamicCall("ReceiveProcDataArr(QVariant, QVariant, 
QVariant, QVariant&)", data)
print(data[3])//It prints the result
print(foo)//It prints 0
Davide Pizzolato
  • 679
  • 8
  • 25
  • Oh, sorry for late response. I gave up this issue long ago and bypassed with using [pydbind](https://github.com/pybind/pybind11). Anyway, I will try this out. Thanks for your answer! :-) – ulismoon Sep 20 '18 at 00:54