PDA

View Full Version : Using Qlibrary on a function that uses arguments



schall_l
1st September 2008, 22:09
Does someone has any experience or has any sample code on how using Qlibrary on a function that has arguments ?

The DLL source code is showing: (Note: I have the DLL only in a compiled form - so I cannot change it prototypes)


short int __stdcall About(unsigned char Device, unsigned char *Version,unsigned char *Manufact) {
...
}

So I've tried to do something like :


typedef short int (*About)(unsigned char, unsigned char *, unsigned char *);

unsigned char m_version[10];
unsigned char m_manufacturer[10];

Qlibrary m_dll("MyLibrary");
About about = (About) m_dll.resolve("About");
if (about) {
about(0, m_version, m_manufacturer);
}

But the content in m_version and in m_manufacturer is not as expected.

wysota
1st September 2008, 22:22
Maybe the function works differently from what you expect from it?

schall_l
8th September 2008, 22:12
Well, I found out that some code executed after the call of the DLL function behaves differently than if the same code is executed before the DLL function call.

If I do something like:


...
GetInfo getInfo = (GetInfo) m_dll->resolve("GetInfo");
if (getInfo) {
QString str;
str = QString("%1 %2 %3 %4 %5 %6").arg(1).arg("aa").arg(3).arg("bb").arg(5).arg(6);
m_ui->setSoftwareVersion(str);
getInfo(m_interfaceNum, 0, tmp_version, tmp_feature, tmp_manufacturer,tmp_controller);
...

it will work...
... but if I do something like:


...
GetInfo getInfo = (GetInfo) m_dll->resolve("GetInfo");
if (getInfo) {
QString str;
getInfo(m_interfaceNum, 0, tmp_version, tmp_feature, tmp_manufacturer,tmp_controller);
str = QString("%1 %2 %3 %4 %5 %6").arg(1).arg("aa").arg(3).arg("bb").arg(5).arg(6);
m_ui->setSoftwareVersion(str);
...

it wont work. (str is filled differently and the line m->ui... brings QT to crash)
If you observe how str is filled in the second case, you will note that the last argument (6) is not filled in correctly. Also in the second case using a fix string in the line m_ui->setSoftwareVersion("my fixed string"); will also make the app to crash, while it does not if the same line is executed before the DLL function call.

I have attached a small project to demonstrate this issue.
The mentionned code is located in can_zcan4usbfx.cpp.
Please note that the DLL provided in my project can be dowloaded directly at http://www.zanthic.com/can4usbfx.htm

Do you have an idea what this could be ?

jacek
9th September 2008, 00:27
Are you sure that tmp_feature, tmp_manufacturer and tmp_controller have correct sizes? Maybe GetInfo returns Unicode strings?

schall_l
9th September 2008, 08:06
Yes, I am sure that the size is correct, although I already made a test giving larger size to these variables, and GetInfo returns correct informations.


// ************************************************** **************************
short int __stdcall GetInfo(unsigned char InterfaceNum,unsigned char DeviceNum,unsigned char *Version,unsigned char *Feature
,unsigned char *Manufact,unsigned char *CANCont)
// Interface Number 0-9 for for than one interface connected (CAN-4-USB only)
// DeviceNum is which CAN controller within an interface if more than one
// Verson will get filled with two bytes for major and minor version
// Feature is an 8 bit flag byte to show which features are availble
// Manufact will be a string up to 20 characters of the board manufacturer name
// CANCont is a byte array with the first character containing the number of CAN
// controllers within this board. The next bytes are a value to show what type of
// CAN controller this is
{
unsigned char USBOutBuf[4];
unsigned char USBInBuf[65];
short int Result,pntr=4;
unsigned char c;

Result=OpenDriver(InterfaceNum);
if (Result<=0) return (Result);

USBOutBuf[0] = DeviceNum;
USBOutBuf[1] = GETSTATSREQ; // command

Result = USBRawCommand(InterfaceNum, USBOutBuf, 2, USBInBuf);
if (Result<0) return(Result); // return error
if (USBInBuf[0]==GETSTATSRESP)
{
*Version++=USBInBuf[1];
*Version++=USBInBuf[2];
*Feature=USBInBuf[3];
while(USBInBuf[pntr]!=0)
*Manufact++=USBInBuf[pntr++]; // load name till 0

*Manufact++=USBInBuf[pntr++]; // load 0

c=USBInBuf[pntr++]; // number of controllers
*CANCont++=c; // save to buffer
while (c--) // loop through the number of controllers
*CANCont++=USBInBuf[pntr++]; // save their type to the buffer

return(ACK);
}
else
return (ERRIMPROPERRESPONSE);
}

After the DLL call Qt is all screwed up.
I am not sure why this should influence the filling of str after the DLL call ?

Anyone has an idea ?

wysota
9th September 2008, 17:27
Is the application multithreaded?

schall_l
9th September 2008, 18:24
Yes, the function in which the DLL is accessed runs within a thread.
But I don't understand how this can affect how filling a simple QString can behave differently before and after the DLL function is called.
I have attached a demo project, including the DLL, in a previous post, that can be used to reproduce the strange behavior I am observing, so that you can have a look if you want.

wysota
9th September 2008, 22:09
Maybe the function is not reentrant?

schall_l
9th September 2008, 22:58
I've got the answer from the Trolltech support.

I negliged the windows calling convention (cf article at http://www.unixwiz.net/techtips/win32-callconv.html) with the consequence of corrupts memory all over the place.

Finally I had to change my typedef from:


typedef short int (*GetInfo)(unsigned char,unsigned char,unsigned char *,unsigned char *,unsigned char *,unsigned char *);
into:


typedef short int (__stdcall *GetInfo)(unsigned char,unsigned char,unsigned char *,unsigned char *,unsigned char *,unsigned char *);

That solved everything.