
Originally Posted by
wysota
If you do get a double call then the only explanation I can see is that the DLL corrupts the stack somehow. I suggest you place a breakpoint on the dll function and step through execution of the code to see if it ends up calling the slot again.
Results are very interesting:
void SelectSource::updateFocusLabel() // this is a slot connected the qSlider
{
qDebug() << "enter";
if (idx)
{
; // for break point purposes...
}
idx++;
cmd
= QString(":focsteps %1,120").
arg(qSliderFocus
->value
());
sendCommandToCam.msg(&vc->Vcam, cmd);
queue.idx--;
qDebug() << "exit";
}
{
int result;
char answer[MAXCHAR_ANS];
*answer = NULL; // clear the string
char *cmd = NULL;
cmdArr = command.toAscii();
cmd = (char*)cmdArr.constData();
result = vc_operate_command(Vcam->Handle, cmd, answer, TIMEOUT_ANS);
if (result != VC_RES_OK)
{ .... }
....
}
void SelectSource::updateFocusLabel() // this is a slot connected the qSlider
{
qDebug() << "enter";
if (idx)
{
; // for break point purposes...
}
idx++;
QString cmd;
cmd = QString(":focsteps %1,120").arg(qSliderFocus->value());
sendCommandToCam.msg(&vc->Vcam, cmd);
queue.idx--;
qDebug() << "exit";
}
QString SendCommandToCam::msg(VC *Vcam, QString command) const
{
int result;
char answer[MAXCHAR_ANS];
*answer = NULL; // clear the string
char *cmd = NULL;
QByteArray cmdArr;
cmdArr = command.toAscii();
cmd = (char*)cmdArr.constData();
result = vc_operate_command(Vcam->Handle, cmd, answer, TIMEOUT_ANS);
if (result != VC_RES_OK)
{ .... }
....
}
To copy to clipboard, switch view to plain text mode
BR @ lines: 8,11,12 + 28,29,30
8; // now idx == 1
(continue)
11;
(continue)
28;
(continue)
29; // DLL call
(continue)
8; //now idx == 2. Note after 29, we did NOT reach 30.
(continue)
11;
(continue)
28;
(continue)
29;
(continue)
30; // now we reach 30, probably because 29 is already running and returns asap.
(continue)
12; // All good. Now idx == 1 again
(continue)
30; // note: after 12 we did NOT reach 28,29.
(continue)
12; // now idx is 0.
qDebug shows:
enter
enter
exit
exit
The trace show that the dll acts as a super return as it runs, and probably force a return for all the calls on the stack (it returns at least SendCommandToCam::msg() and then SelectSource::updateFocusLabel(), so I guess it forces a returns on the upper functions as well). This is why Qt thinks we have returned from the slot. In fact we have returned and this is also why we don't see any imbrication or recursive calls on the stack. So Qt is probably starting a new cycle on the event loop.
Whats interesting here is the way the DLL is able force a return (that could be a bug, for example if you clear the stack and readjust the program counter so it points to a base address from which the prog can restart smoothly). But then, the DLL forces a passage from line 12 to 30 without passing by 28, 29 like to continue where it stopped before.
A way to do that for the dll would be to run in another thread and conrol the stack of the working thread, and then clear the program counter (PC), save the Stack (eg save the stack pointer on the stack and restart a new stack from here) the first time, and then reverse everything at some point.
Added after 24 minutes:

Originally Posted by
d_stranz
This looks like a possible source of stack corruption. From the names, it would appear that "Answer" is a buffer into which the DLL is going to place some reply to the command. From the calling convention, it would appear that you must allocate this buffer yourself and pass is a pointer to it. What does the documentation say about how big this buffer must be? (Or does it say anything at all?) What do the contents look like after the call? Are you sure it is a char * and not a wchar *? Do you need to clear it and set the first character to NULL ('\0') before the call? What about "Command"? Does the DLL expect this to be a NULL-terminated string?
I'd start with the "Answer" :-) and go from there.
Like you and I wysota I tend to believe the dll is messing up the stack, either because of a bug or on purpose.
So yes as shown in the previous code I posted the char*answer must be allocated. The SDK says:
Command: The character string containing the command
Answer: Accepts the answer from camera. The length of the answer is to be defined corresponding to the expected maximum answer length.
"expected maximum answer length" How informative lol. So I allocated 5K by default, knowing by experience that the answer never seems longer than say 50 chars. To be sure, I allocated 500KBytes. Same behavior.
>What do the contents look like after the call?
I always display the content on a console after the call. It looks like a normal 20 chars string, null char terminated, that returns the command entered. It's a form of ack.
>Are you sure it is a char * and not a wchar *?
From the dll's SDK it's a char. From a dll analyzer, it's a char as well, so no wchar.
>Do you need to clear it and set the first character to NULL ('\0') before the call?
yes, always did as shown in code above.
>What about "Command"? Does the DLL expect this to be a NULL-terminated string?
The only info I have is the one cited above. As it's a very basic and low level dll, I assume it is a null terminated string as returned by QByteArray::constData(); To be noticed that ::constData() returns a const, hence the cast I did as "cmd = (char*)cmdArr.constData();".
Bookmarks