PDA

View Full Version : QAxWidget Programming: pass by reference



NeuroC++
3rd March 2014, 16:25
I have been using a ActiveX widget in my C++ program using the QAxWidget class. It works fine for all the functions that return a single value and have input arguments only. However, when I try to pass a variable by reference which I will use later as a return value, it won't compile because QVariant can't be instantiated with a pointer or it has errors at runtime. The documenation for the ActiveX widget I'm using is geared for Visual Basic so I'm probably using the wrong syntax. Here is a function that works:

************** LIBRARY DOCUMENTATION **************

Motor Method SetAbsMovePos

See Also Example Code


Visual Basic Syntax

Function SetAbsMovePos(lChanID As Long, fAbsPos As Single) As Long


Parameters

lChanID - the channel identifier

fAbsPos - the absolute position associated with the specified channel


Returns

MG Return Code


Details

This method sets the absolute position to which the channel specified by the lChanID parameter will move, the next time the MoveAbsolute method is called. The position is set to the value specified in the fAbsPos parameter and is measured from the home position, in real world units (mm or degrees).

The lChanID parameter takes values specified by the HWCHANNEL enumeration.

Note: On dual channel units, the system cannot set the absolute position of both channels simultaneously, and the use of CHANBOTH_ID is not allowed.

To get the absolute position for a particular channel, see the GetAbsMovePos method.

************** MY FUNCTIONING IMPLEMENTATION **************

QAxWidget* hMotor;
hMotor = new QAxWidget();
hMotor->setControl("MGMOTOR.MGMotorCtrl.1");
hMotor->setProperty("HWSerialNum",QVariant(67839858));
hMotor->dynamicCall("StartCtrl");
double pos(10);

hMotor->dynamicCall("SetAbsMovePos(QVariant,QVariant)",chanID,QVariant(pos));

hMotor->dynamicCall("MoveAbsolute(QVariant,QVariant,QVariant)",chanID,1);



************** FUNCTION I WANT TO USE **************

Motor Method GetPosition

See Also Example Code


Visual Basic Syntax

Function GetPosition(lChanID As Long, pfPosition As Single) As Long


Parameters

lChanID - the channel identifier

pfPosition - the current position of the associated channel


Returns

MG Return Code


Details

This method obtains the present position for the channel(s) specified by the lChanID parameter, and returns a value in the pfPosition parameter.

If a calibration file has been associated with the channel using the APT Config utility, the method returns the calibrated position. If no calibration file has been associated, then the returned position is uncalibrated. Refer to the helpfile in the APT Config utility for further details on using position calibration files.

Note that the position values returned are derived from either the ‘Microstep Count’ or the Encoder Count, dependent on the positioning mode selected. See the encoder operation section for more information.

The position of the stage associated with the specified channel is determined by its displacement from the 'Home' position.

The lChanID parameter takes values specified by the HWCHANNEL enumeration.


************** MY SYNTAX ATTEMPTS AND ERROR OUTPUT **************

#include <QApplication>
#include <QAxWidget>
#include <QDebug>
#include <QThread>

int main(int argc, char *argv[])
{
QApplication g(argc,argv);

QAxWidget hMotor;
QVariant chanID = QVariant(0);
hMotor.setControl("MGMOTOR.MGMotorCtrl.1");
hMotor.setProperty("HWSerialNum",QVariant(67839858));
hMotor.dynamicCall("StartCtrl");
hMotor.dynamicCall("EnableHWChannel(QVariant)",chanID);
QThread::sleep(1); // Give it time to enable the channel

double pos(5);
hMotor.dynamicCall("SetAbsMovePos(QVariant,QVariant)",chanID,QVariant(pos));
hMotor.dynamicCall("MoveAbsolute(QVariant,QVariant,QVariant)",chanID,0);

double outPos;
hMotor.dynamicCall("GetPosition(QVariant,QVariant)",chanID,QVariant(outPos));
qWarning() << outPos;
hMotor.dynamicCall("StopCtrl");


return (0);

}

CONSOLE OUTPUT

QAxBase: Error calling IDispatch member GetPosition: Type mismatch in parameter
1
1.39065e-309
Press <RETURN> to close this window...


All the functions work except the "GetPosition" one. The outPos should a double between 0 and 100, not 1.39e-309 (bad memory). This is just a simple example and I've used the other functions probably 100 times and I'm sure they work. If I try QVariant(&outPos) as the argument, I get a compile error (QVariant::QVariant(*void) is private...). Any ideas?

Thanks in advance!

ChrisW67
3rd March 2014, 23:18
I am not certain how a pointer to a float can be passed as the second argument but I would try:


double outPos(0.0);
QVariant retCode = hMotor.dynamicCall("GetPosition(int, float&)",chanID, outPos);

The parameter types come from the lookup in the docs.

NeuroC++
3rd March 2014, 23:26
Thanks, I appreciate the help.

I just tried your suggestion. It gives the same error as before.


QAxBase: Error calling IDispatch member GetPosition: Type mismatch in parameter
1
0
Press <RETURN> to close this window...

ChrisW67
4th March 2014, 02:08
How about this?


float outPos(0.0);
QVariant retCode = hMotor.dynamicCall("GetPosition(int, float*)",chanID, &outPos);

I don't really expect this to work, just covering the bases.

NeuroC++
4th March 2014, 02:16
Yeah, if I do that it gives the "QVariant::QVariant(*void) is private" compile error. I've even tried casting the pointer to "outPos" into an int that I put into a QVariant which I then passed to the function. It compiled but still gave a type mismatch error at runtime.

NeuroC++
5th May 2014, 19:27
bump. Still can't solve this problem.

Added after 1 42 minutes:

I found a call that doesn't throw a compile or runtime error but the value doesn't change.


float outPos(1.1);
hMotor->dynamicCall("GetPosition(int,float&)",chanID,outPos);


My output is "1.1" after I call the function. Any ideas?

NeuroC++
18th June 2015, 23:49
It's a year later and I finally had a chance to debug this. So, without any further delay, voila!


bool flag(0);
QList<QVariant> args;
args.push_back(QVariant(flag));
motor->dynamicCall("GetHWCommsOK(QVariant&)",args);
return args[0].toBool();

and it returns the value set by the ActiveX control. Hurray! Sorry to dig up an old thread, but I wanted the solution to be out there somewhere. I'll probably forget and have to come back here to remind myself.