PDA

View Full Version : dynamicCall and QByteArray - strange characters



franco.amato
17th April 2010, 17:25
Hi to all,
doing some test with a com object seems that a com routine that I call with dynamicCall returns a QByteArray or a QString.
Looking at examples of call of such routine seems that it returns an array of bytes where every element is a pointer to a string

I did some tests as this:

QByteArray array = obj->dynamicCall("routine(QString)", "value").toByteArray();
Debugging with visual studio and doing some cout ( qDebug() << array.data() ) I can see very strange characters like this "‰*" in both case, using QByteArray and QString.
The routine called with dymanicCall comunicate with a chinese fingerprint reader. Maybe this is the reason I get such strange characters?

Looking at doc and visual basic example the value returned should be an array of bytes -> returned_value[value1,value2,value3, value4..];

and

value1 = value2 = value3 = should points to a string.

How can I get the value of every value without getting these strange characters?
I hope to get help wysota where are you?

Regards

ChrisW67
17th April 2010, 22:40
Can you run the dumpcpp utility against the com object you are working with?


cd somewheresafetowrite
dumpcpp c:\windows\system32\comctl32.ocx

The resulting cpp and h file should allow you to more directly access the COM objects by simply instantiating them in the typical C++ fashion:


ComctlLib::TreeView m_treeView;
...
m_treeView.SetBorderStyle(ComctlLib::ccFixedSingle );



The process can be largely automated by:

client.pro


TEMPLATE = app
CONFIG += qaxcontainer
TARGET = client
DEPENDPATH += .
INCLUDEPATH += .
RC_FILE = client.rc
// {6B7E6392-850A-101B-AFC0-4210102A8DA7} is the TypeLib value from the class concerned.
TYPELIBS = $$system( dumpcpp -getfile {6B7E6392-850A-101B-AFC0-4210102A8DA7} )
isEmpty(TYPELIBS) {
message("Tree control type library not found!")
REQUIRES += COMCTL.TreeView
}
else: {# Input
SOURCES += main.cpp
}

franco.amato
17th April 2010, 22:52
Can you run the dumpcpp utility against the com object you are working with?


cd somewheresafetowrite
dumpcpp c:\windows\system32\comctl32.ocx

The resulting cpp and h file should allow you to more directly access the COM objects by simply instantiating them in the typical C++ fashion:


ComctlLib::TreeView m_treeView;
...
m_treeView.SetBorderStyle(ComctlLib::ccFixedSingle );



The process can be largely automated by:

client.pro


TEMPLATE = app
CONFIG += qaxcontainer
TARGET = client
DEPENDPATH += .
INCLUDEPATH += .
RC_FILE = client.rc
// {6B7E6392-850A-101B-AFC0-4210102A8DA7} is the TypeLib value from the class concerned.
TYPELIBS = $$system( dumpcpp -getfile {6B7E6392-850A-101B-AFC0-4210102A8DA7} )
isEmpty(TYPELIBS) {
message("Tree control type library not found!")
REQUIRES += COMCTL.TreeView
}
else: {# Input
SOURCES += main.cpp
}


Hi,
I executed the dumpcpp on my dll ( the com object) but it doesn't generated any *.h or *.cpp
What can I do?

ChrisW67
17th April 2010, 22:58
Did you write the com object yousrself? Using QAxServer? If so you probably have a file ending .tlb as part of the build process, and you can put this file name directly in TYPELIBS.

wysota
17th April 2010, 23:00
wysota where are you?
I'm having a bad evening.

Besides what was already written I could advise you to check the type of variant returned by dynamic call.


QVariant var = obj->dynamicCall(...);
qDebug() << var->typeName();

franco.amato
17th April 2010, 23:01
Did you write the com object yousrself? Using QAxServer? If so you probably have a file ending .tlb as part of the build process, and you can put this file name directly in TYPELIBS.

No I didn't write the com object. It com from a finger print sdk I have. I have it in a compiled dll.
I'm not sure now if I have a tlb file as I'm out of office. If I have it what can I do? And if I don't have it?

franco.amato
17th April 2010, 23:04
I'm having a bad evening.

Besides what was already written I could advise you to check the type of variant returned by dynamic call.


QVariant var = obj->dynamicCall(...);
qDebug() << var->typeName();

Ok I'll check tomorrow with the typeName,
for now thank you.

Regards

ChrisW67
18th April 2010, 00:16
No I didn't write the com object. It com from a finger print sdk I have. I have it in a compiled dll.
I'm not sure now if I have a tlb file as I'm out of office. If I have it what can I do? And if I don't have it?

You can try

TYPELIBS += C:\path\to\your\fingerprint.dll

which seems to work OK for me for at least some COM objects.

franco.amato
19th April 2010, 06:09
You can try

TYPELIBS += C:\path\to\your\fingerprint.dll

which seems to work OK for me for at least some COM objects.

If I also have the *.tlb I have to do

TYPELIBS += C:\path\to\your\fingerprint.dll
And

TYPELIBS += C:\path\to\your\fingerprint.tlb?

ChrisW67
19th April 2010, 07:26
If you have the TLB file then list it otherwise try listing the DLL or OCX file itself. One or the other, not both.

franco.amato
20th April 2010, 17:26
I'm having a bad evening.

Besides what was already written I could advise you to check the type of variant returned by dynamic call.


QVariant var = obj->dynamicCall(...);
qDebug() << var->typeName();

Dear Wysota the result of the
qDebug() << var->typeName(); is QByteArray but I don't know how to manage the data. It returns strange characters.

I also generated the *.cpp and *.h files with dumpcpp.
This is the prototype of the routine that give problems to me (from the generated .h):

/*
Method GetUserData
*/
inline QVariant GetUserData(const QString& CardID);

and the member function implementation ( always in the *.h generated )

inline QVariant oTerminal::GetUserData(const QString& CardID)
{
QVariant qax_result;
void *_a[] = {(void*)&qax_result, (void*)&CardID};
qt_metacall(QMetaObject::InvokeMetaMethod, 71, _a);
return qax_result;
}


I attached here a shot of the visual studio to see the returned value. I hope you can help me.

Regards

franco.amato
20th April 2010, 18:36
The resulting cpp and h file should allow you to more directly access the COM objects by simply instantiating them in the typical C++ fashion:


ComctlLib::TreeView m_treeView;
...
m_treeView.SetBorderStyle(ComctlLib::ccFixedSingle );





Hi, I don't understand a thing:
I don't have to use the new operator to instantiate the objects?

wysota
20th April 2010, 19:22
Let's ask this first - what would you expect the byte array to contain?

franco.amato
20th April 2010, 22:15
Let's ask this first - what would you expect the byte array to contain?

Wysota here the very poor doc I have respect to such routine:

Function: GetUserData
Parameter: CardID(string/10)
Description: Get User Data
Return values: ArrayList

So I expect some sort of array list with different fields as the "set" routine accepts these parameters:

Function: SetUserData
Parameters:
CardID(string/10)
OverWrite(0: no overwrite. If ID is already registered, return with result 06.,1: overwrite.)
idxDesignation
idxDepartment
FirstName(string /15)
LastName(string /15)
idxGroup (integer/0~255)
Status(1 : Activate, 0 : Deactivate)
WorkMode(0:finger+pass ,1:finger,2:pass,3:finger or pass,4:Only Crad,5:Only from external Reader,6:Matching on Mifare card)
WorkTimeStart()
WorkTimeEnd()
EmployeeID
RegisterMode( Finger =1, Password = 2, Finger and Password = 3, Card=4, Max=4)
CheckExpire
ExpireDateStart
ExpireDateEnd
Password(string/10)
NF(Number of fingerprint data per user Max. 2)
TemplateSize
FingerData (byte,User Fingerprint data total size depends on the number of fingerprints registered per user)

Description: Set User Data
Return values: True: Successfully

I think the Get routine should returns the same parameters I pass in the Set routine.

Best Regards

wysota
20th April 2010, 22:30
Maybe you didn't call the routine correctly and it reports some error or something like that?

franco.amato
20th April 2010, 22:39
Maybe you didn't call the routine correctly and it reports some error or something like that?

No I have no errors, and also visual studio says the QByteArray has a size of 441 elements.
I'm thinking to do a com wrapper in c# and call the com routine from it to see the result but from my Qt code how can I get the parameters?

wysota
20th April 2010, 22:41
No I have no errors, and also visual studio says the QByteArray has a size of 441 elements.
So maybe everything is there? Try casting the contents of the array to the structure you should be getting and reading the data.

franco.amato
20th April 2010, 22:43
So maybe everything is there? Try casting the contents of the array to the structure you should be getting and reading the data.

I don't have such structure. How can I do it?

wysota
20th April 2010, 22:54
I meant the ArrayList (or its C++ equivalent) or whatever the return type of the call should be.

franco.amato
20th April 2010, 23:03
I meant the ArrayList (or its C++ equivalent) or whatever the return type of the call should be.

Do you mean something like this?
QList<QString> list = static_cast<QList<QString>>(ba.data()) ?

wysota
20th April 2010, 23:08
No, I meant the structure you would be getting if you were calling the method directly using WinAPI's COM API. I just can't say it more clearly. Or just dump the byte array to the console in ascii, see what is there and try to guess its stucture.

zAAm
20th April 2010, 23:43
No, I meant the structure you would be getting if you were calling the method directly using WinAPI's COM API. I just can't say it more clearly. Or just dump the byte array to the console in ascii, see what is there and try to guess its stucture.

If I can try to put it a bit more clearly:

Your dynamic call returns a QByteArray with 441 elements right? So all those return types (CardID, OverWrite, idxDesignation and all those) you listed should be contained in those 441 elements.
What wysota means by structure is how those 441 elements are divided to produce the return types ie. CardID is a string of size 10, OverWrite a byte(or bit) etc... If you have that structure you can try to cast the QByteArray to that structure. Otherwise you'll need to determine the structure as wysota mentioned - by dumping to ascii and trying to figure out the type of each return type. :cool:

ChrisW67
20th April 2010, 23:50
Hi, I don't understand a thing: I don't have to use the new operator to instantiate the objects?
That depends on the lifetime you expect the object (m_treeView in my example) to have. On the stack is fine for a short lifespan limited by scope, on the heap would be more typical. The code generated by dumpcpp connects to COM control at the time the wrapper object is constructed and doesn't care how the object came to be.

You have had success with dumpcpp creating some wrappers. The generated classes should manage marshalling COM response into qt and/or C++ structures for you make for more direct access (adjust names as needed):


#include "generated_header.h"
...
terminalLib::oTerminal *comObject;

comObject = new terminalLib::oTerminal(this);
QVariant result = oTerminal->GetUserData(QString("some card id thingy"));
delete comObject;

If you dig around in the generated H and CPP file you might find a definition of "ArrayList" (or it may be intended to be an opaque blob although this seems unlikely). You may also find references to a Windows help file that matches the type library.

Could you post (attach) the generated header file?

ChrisW67
21st April 2010, 00:08
If the QVariant returned is of type QByteArray then the COM return was a SAFEARRAY(BYTE) according to the QAxBase documentation.
You might find this useful:
http://www.roblocher.com/whitepapers/oletypes.aspx
http://msdn.microsoft.com/en-us/library/cc237826%28PROT.13%29.aspx

franco.amato
21st April 2010, 02:55
That depends on the lifetime you expect the object (m_treeView in my example) to have. On the stack is fine for a short lifespan limited by scope, on the heap would be more typical. The code generated by dumpcpp connects to COM control at the time the wrapper object is constructed and doesn't care how the object came to be.

You have had success with dumpcpp creating some wrappers. The generated classes should manage marshalling COM response into qt and/or C++ structures for you make for more direct access (adjust names as needed):




#include "generated_header.h"
...
terminalLib::oTerminal *comObject;

comObject = new terminalLib::oTerminal(this);
QVariant result = oTerminal->GetUserData(QString("some card id thingy"));
delete comObject;

If you dig around in the generated H and CPP file you might find a definition of "ArrayList" (or it may be intended to be an opaque blob although this seems unlikely). You may also find references to a Windows help file that matches the type library.

Could you post (attach) the generated header file?

Dear Chris,
for sure. Tomorrow I'll post the .h file.

Regards

franco.amato
21st April 2010, 02:58
If I can try to put it a bit more clearly:

Your dynamic call returns a QByteArray with 441 elements right? So all those return types (CardID, OverWrite, idxDesignation and all those) you listed should be contained in those 441 elements.
What wysota means by structure is how those 441 elements are divided to produce the return types ie. CardID is a string of size 10, OverWrite a byte(or bit) etc... If you have that structure you can try to cast the QByteArray to that structure. Otherwise you'll need to determine the structure as wysota mentioned - by dumping to ascii and trying to figure out the type of each return type. :cool:

If I well understood I have to first create such structure with struct and then cast the returned value to such structure? Or I'm wrong?
Can I have some pseudo-code?

wysota
21st April 2010, 07:53
If I well understood I have to first create such structure with struct and then cast the returned value to such structure?
Did you try entering "ArrayList C++" in your favourite search engine and reading what pops up?

franco.amato
21st April 2010, 16:36
Did you try entering "ArrayList C++" in your favourite search engine and reading what pops up?

The arrayList is not the problem. The problem is the return value that's QByteArray

franco.amato
21st April 2010, 16:48
Could you post (attach) the generated header file?

I tried to send the files you asked for but the forum says they are bigger than the limit.
If you have a mail address I can send them to you.

Regards

wysota
21st April 2010, 17:12
Compress them. Then you will be able to attach them to your post. And only send the relevant file (.h).

franco.amato
21st April 2010, 17:29
Compress them. Then you will be able to attach them to your post. And only send the relevant file (.h).

Ok Wysota thank you.
I compressed PallyCom.h in PallyCom.zip ( 8K )

Regards

franco.amato
21st April 2010, 20:11
Compress them. Then you will be able to attach them to your post. And only send the relevant file (.h).

Wysota I saw some data calling the routine in a C# console application and I had to do a conversion byte to ascii to see something.
I think if for that that I can not see nothing in Qt. How can I convert the bytearray in ascii?
I also saw that the stream of data contains lots of '\0' and for that maybe I can not see well all characters.

Best

wysota
21st April 2010, 20:33
How can I convert the bytearray in ascii?
What did you already try to do it?

franco.amato
21st April 2010, 21:11
What did you already try to do it?

Hi,
first I have know how to access to every byte contained in the bytearray and discover how Qt manage the '\0' as in the
returned stream I have lots of such character

wysota
21st April 2010, 21:13
Hi,
first I have know how to access to every byte contained in the bytearray and discover how Qt manage the '\0' as in the
returned stream I have lots of such character

Then open the documentation of QByteArray and read it. I can tell you that Qt doesn't "manage" null bytes in any way. They are bytes like any other.

franco.amato
21st April 2010, 22:16
Then open the documentation of QByteArray and read it.
This is was I already did many times


I can tell you that Qt doesn't "manage" null bytes in any way. They are bytes like any other.

This is the result of the routine call in a cmd line app written in C#:


"I??\0\0xml;q=0.Franco\0\0\0\0\0\0\0\0\0Amato\0\0\ 0\0\0\0\0\0\0\0\0\0\0\0AAAAAAAAAAAAAAA=0\0\n \n0987654321`E?\"UF ??\fCQ????O\"D ?\v2??(E??\n2F?D?\fH1\b\vH???\nIae?.???(?`>?/?p<?;M???????:????\"8??`:?!???PQ?\r??`'?`2??Q)\n??#3?????#34 ????\"34????\"34O???\"34O???\"#3D???#4D???#4D???#4D???34D???\"3DD???#DDE???4DTE???4UUEo??EUUUo???VffUo???fff f???wwff????wwvg?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0"

You can see many '\0' but why debuggind with visual studio my Qt app I can not see the same string that's should contained in the QByteArray? And also I really don't understand which characteres are these:     ??

I hope you can help me

ChrisW67
21st April 2010, 23:10
You still seem to be expecting a nice human readable string when what you are being passed is a binary data structure. The docs for the COM server say it returns an ArrayList (a .Net/C# data type of some sort) but this has to be translated to something that can be sent through the COM interface, which must remain language agnostic. The QAxBase docs imply this structure is a SAFEARRAY(BYTE). I'd hazard a guess it's a single dimensional array of VT_VARIANT entries.

In your C++ Qt application you receive a QByteArray. Use QByteArray::toHex() to dump the first 24 or 32 bytes. Then sit and try to marry the bytes to the SAFEARRAY structures described here;
http://msdn.microsoft.com/en-us/library/aa913233.aspx


typedef struct FARSTRUCT tagSAFEARRAY {
unsigned short cDims; // two bytes
unsigned short fFeatures; // two bytes
unsigned short cbElements; //two bytes
unsigned short cLocks; // two bytes
unsigned long handle; // four bytes
void HUGEP* pvData; // four bytes
SAFEARRAYBOUND rgsabound[1]; // structure below repeated if more than one dimension in array
} SAFEARRAY;

typedef struct tagSAFEARRAYBOUND {
unsigned long cElements; // four bytes
long lLbound; // four bytes
} SAFEARRAYBOUND;

Does the number of dimensions make sense? Do the array bounds make sense? If so, read here:
http://msdn.microsoft.com/en-us/library/ms221145.aspx
You might want to use your favourite search engine to look for a C++ wrapper for SAFEARRAYs.

wysota
21st April 2010, 23:42
This is was I already did many times
Then do it again and again until you find something you consider useful for writing a routine for dumping the byte array in ascii (or hex or whatever you find important). I can already tell you there is no method in QByteArray that will do the task for you - you have to come up with a proper algorithm yourself. Otherwise you won't learn anything and next time you will again ask someone for help instead of trying to solve the problem on your own first.

franco.amato
22nd April 2010, 00:46
Then do it again and again until you find something you consider useful for writing a routine for dumping the byte array in ascii (or hex or whatever you find important). I can already tell you there is no method in QByteArray that will do the task for you - you have to come up with a proper algorithm yourself. Otherwise you won't learn anything and next time you will again ask someone for help instead of trying to solve the problem on your own first.

My problem is not convert byte to ascii,
my problem is understand why QByteArray doesn't contain the data as It should

wysota
22nd April 2010, 09:54
my problem is understand why QByteArray doesn't contain the data as It should
How do you know it doesn't contain the data?

franco.amato
22nd April 2010, 15:17
How do you know it doesn't contain the data?

Because from a cmd line software written in C# calling the same routine with the same parameter, importing as reference such com object I can see this (debugging with visual studio):


"I??\0\0xml;q=0.Franco\0\0\0\0\0\0\0\0\0Amato\0\0 \0\0\0\0\0\0\0\0\0\0\0\0AAAAAAAAAAAAAAA=0\0\n \n0987654321`E?\"UF ??\fCQ????O\"D ?\v2??(E??\n2F?D?\fH1\b\vH???\nIae?.???(?`>?/?p<?;M???????:????\"8??`:?!???PQ?\r??`'?`2 ??Q)\n??#3?????#34????\"34????\"34O???\"34O? ??\"#3D???#4D???#4D???#4D???34D???\"3DD? ??#DDE???4DTE???4UUEo??EUUUo???VffUo???ffff?? ?wwff????wwvg?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0"

And debugging the same routine but written in Qt I can not see nothing, only 4 characters.
It show the correct size ( 441 bytes ) but I can not see its content as in the case of C#. I also did

char* data = ba.data();
qDebug() << content of data; //<--pseudo code

but I even this way I can't see the data.

wysota
22nd April 2010, 15:27
And debugging the same routine but written in Qt I can not see nothing, only 4 characters.
Look at what the C# method returns - what is the value of the 5th character? How does C interpret such characters in strings? Now if you answer yourself these questions, try to come up with how to avoid this effect using expressions C/C++ languages offer such as loops and conditionals.

franco.amato
22nd April 2010, 15:31
Look at what the C# method returns - what is the value of the 5th character? How does C interpret such characters in strings? Now if you answer yourself these questions, try to come up with how to avoid this effect using expressions C/C++ languages offer such as loops and conditionals.

Wysota, for that.
This is exactly what I asked last time...how can I manage null caracters? I know that in c/c++ is a string termination character, but I need them as are part of the raw data

wysota
22nd April 2010, 15:45
This is exactly what I asked last time...how can I manage null caracters?
Come on, man... this is a trivial programming task. How do you check if a character in an array is some special character and treat it in differently than others? What would you do if you had an array of integers and were asked to display the ones with even values on the console?

franco.amato
22nd April 2010, 20:01
Come on, man... this is a trivial programming task. How do you check if a character in an array is some special character and treat it in differently than others? What would you do if you had an array of integers and were asked to display the ones with even values on the console?

Wysota you didn't understand me. I know check a character in an array.
What I don't understand is why the debugger doesn't show me the characteres in the Qt program and yes in the C# program. Could you see the picture I sent last time?

wysota
22nd April 2010, 20:04
What I don't understand is why the debugger doesn't show me the characteres in the Qt program and yes in the C# program.
Because it doesn't treat null characters in a QByteArray in a special way and it does that with the C# data structure. That's why you need to dump the contents of the array yourself in such a way that null characters don't prevent you from seeing the whole 442 bytes of the array.

I don't really see a reason for all this discussion. If you know how to dump the contents of the byte array then do it instead of wondering why something works here or there.

ChrisW67
22nd April 2010, 21:55
It's already been mentioned back at post #37: QByteArray::toHex()

You could equally well use QByteArray::toPercentEncoding() or roll-your-own by looping over QByteArray::size() bytes.

wysota
22nd April 2010, 22:31
It's already been mentioned back at post #37: QByteArray::toHex()

You could equally well use QByteArray::toPercentEncoding() or roll-your-own by looping over QByteArray::size() bytes.

Yeah... he will surely learn something if you give him all the answers on a silver platter...

ChrisW67
22nd April 2010, 23:07
Even with this offering on a platter there's still a long way to go, most of which has nothing to do with Qt.

franco.amato
22nd April 2010, 23:10
Yeah... he will surely learn something if you give him all the answers on a silver platter...

How can I understand if I don't know what I have to do??
I know that I have to first convert al ba bytes to Ascii ( I'll iterate over all bytes of the ba ).
I don't understand why I should convert to hex or to toPercentEncoding()

ChrisW67
22nd April 2010, 23:18
The bytes in the QByteArray are not a NUL terminated ASCII string although there appear to be string fragments amongst them. If it were a simple ASCII string then you'd see no gibberish when the raw data was dumped to the console. Even your C# test program doesn't think it is a straight ASCII NUL terminated string. The QByteArray contains a data structure that might be interpretable with some manual work to verify the structure. This work is going to much easier if you can see the actual values in each byte, which is why hex would be useful.

franco.amato
22nd April 2010, 23:30
The bytes in the QByteArray are not a NUL terminated ASCII string although there appear to be string fragments amongst them. If it were a simple ASCII string then you'd see no gibberish when the raw data was dumped to the console. Even your C# test program doesn't think it is a straight ASCII NUL terminated string. The QByteArray contains a data structure that might be interpretable with some manual work to verify the structure. This work is going to much easier if you can see the actual values in each byte, which is why hex would be useful.

So I should implement some fomHexToAscii routine right? Sometime my poor english doen't help me.
My problem is this: I have to get the bytearray, parse them, populate a new structure and re-write some data but for that I have to see with my eyes the meaning of some bytes as my documentation is very very poor and I have to guess where the name and surname position are, the cardId, etc...
I hope you can understand me. The only way I can do it is to see some bytes in a human been readable way as fortunately C# does ( personally I hate C# )

wysota
22nd April 2010, 23:36
How can I understand if I don't know what I have to do??
Take a sheet of paper and a pen. At the top write down what is that you want to achieve exactly - think it terms "what I want to have" not "how I would like to do it" or "what technologies I have to use". Then try to determine the algorithm needed to achieve the goal and write it down below in a form of a numbered list. Leave some space between items. Now take some two objects and cover everything except the first point on your newly created list. Think about the problems related to solving this one step and ways to do it. Write them down as subitems of the item in the list. You can leave some space between items. Then continue with the next step and repeat the process until you reach the end of your list. Then go back and think about each of the subitems on your list and expand those that need more steps with new subitems. At the end you should have a complete list of things you need to do and the point of doing all that is to focus on one thing at a time and finding a way to solve your problem on your own. Forget about Qt, forget about C++, C#, DLLs, COM or any technology you are using. Solve the abstract task using abstract means on a piece of paper, only then think how to implement them in this or that technology. If you have a problem with any items on your list then think how to obtain the same goal using different means and replace the item with a new one.

If you don't know why you should use toHex() or toPercentEncoding() then don't use them, think about a result that you want to obtain, then create an algorithm for it and only then look for means of implementing it. If you have problems with creating the algorithm then ask for help here or somewhere else but when you are given the answer, don't jump to the next point but rather check if you understand every aspect of things you need to do. If you have a "my method returns a FooBarThingy", ask yourself (and your favourite search engine) what "FooBarThingy" is, where it comes from, what it represents and how to use it in different technologies. Don't rush here asking "how do I use this FooBarThingy thingy...". I have already told you this a couple of times - if you don't make a leap past your current abilities, you won't learn. Ask yourself why things happen, verify your assumptions, reject them if they are wrong and find new ones until you come up with a theory that is consistent with what you observe. Then write a small application to verify your thesis.

Geeez... this starts to look like an article... If just writing my dissertation was as easy as writing posts here... :rolleyes:

franco.amato
23rd April 2010, 00:22
Take a sheet of paper and a pen. At the top write down what is that you want to achieve exactly - think it terms "what I want to have" not "how I would like to do it" or "what technologies I have to use". Then try to determine the algorithm needed to achieve the goal and write it down below in a form of a numbered list. Leave some space between items. Now take some two objects and cover everything except the first point on your newly created list. Think about the problems related to solving this one step and ways to do it. Write them down as subitems of the item in the list. You can leave some space between items. Then continue with the next step and repeat the process until you reach the end of your list. Then go back and think about each of the subitems on your list and expand those that need more steps with new subitems. At the end you should have a complete list of things you need to do and the point of doing all that is to focus on one thing at a time and finding a way to solve your problem on your own. Forget about Qt, forget about C++, C#, DLLs, COM or any technology you are using. Solve the abstract task using abstract means on a piece of paper, only then think how to implement them in this or that technology. If you have a problem with any items on your list then think how to obtain the same goal using different means and replace the item with a new one.

If you don't know why you should use toHex() or toPercentEncoding() then don't use them, think about a result that you want to obtain, then create an algorithm for it and only then look for means of implementing it. If you have problems with creating the algorithm then ask for help here or somewhere else but when you are given the answer, don't jump to the next point but rather check if you understand every aspect of things you need to do. If you have a "my method returns a FooBarThingy", ask yourself (and your favourite search engine) what "FooBarThingy" is, where it comes from, what it represents and how to use it in different technologies. Don't rush here asking "how do I use this FooBarThingy thingy...". I have already told you this a couple of times - if you don't make a leap past your current abilities, you won't learn. Ask yourself why things happen, verify your assumptions, reject them if they are wrong and find new ones until you come up with a theory that is consistent with what you observe. Then write a small application to verify your thesis.

Geeez... this starts to look like an article... If just writing my dissertation was as easy as writing posts here... :rolleyes:

I simply would to know how to read and interpret data got with ActiveQt and QByteArray ( that IIRC are Qt classes, are not classes written by me or by my sister ). It's so difficult?
I don't need your sermon as you do everytime, you're not my father. So if I can not ask here qt-related things I don't understand why does this forum exist.

Kind Regards

wysota
23rd April 2010, 00:30
The thing is your problem is not Qt related. The role of Qt ends at the point where you get the array of bytes. Qt gave you what ActiveX returned, it is your task to interpret the result and I think this is what you fail to understand during the last 20 or so posts...

And let's not get into what each of us does every time because we'd have to focus on your "please give me example code" posts too. I'm not going to convince you to learn ever again, don't worry. It's your decision what you do with your life.

franco.amato
23rd April 2010, 02:05
The thing is your problem is not Qt related. The role of Qt ends at the point where you get the array of bytes. Qt gave you what ActiveX returned, it is your task to interpret the result and I think this is what you fail to understand during the last 20 or so posts...

And let's not get into what each of us does every time because we'd have to focus on your "please give me example code" posts too. I'm not going to convince you to learn ever again, don't worry. It's your decision what you do with your life.

In this last post I never asked for "source code" and I didn't write "please give me example code" but I asked for pseudo-code in post #26 "Can I have some pseudo-code?".
If for you is so hard to give some line of "pseudo code" as administrators of a programming forum or experts ( or Masters of Zen ) should do, so I didn't undersand the meaning of a programming forum, or maybe you're jealous of your knowledge. Personally when someon ask for my help in my work I'm very happy to help him as I can.
Personally I'm an hardware designer and I don't love programming gui so for me is a big effort to come here and ask for something, do you think I'm having fun coming here and write post after post to get nothing? Is very frustrated and personally you can change my programming level to beginner or intermediate.

Bye

ChrisW67
23rd April 2010, 02:42
1. Determine what the data structure actually is. My best guess is in post #37 and its content may be a serialised C# object.
1a. Match bytes from the byte array against candidates for the data structure and see if they make sense. A hex dump would be useful here.
1b. If you can see recognisable bits in the data (like your name) then look at the bytes around it to see if they make any sense, e.g. is the preceding byte, short, or long value the length of the string?
1c. Anything else that might help break the code (this is not unlike cracking weak encryption).
2. If you match the structure and it has a name then search for a wrapper that can handle that data structure.
3. Failing 2. write one yourself.

You are still at step 1 and the road is rocky.

franco.amato
23rd April 2010, 02:46
1. Determine what the data structure actually is. My best guess is in post #37 and its content may be a serialised C# object.
1a. Match bytes from the byte array against candidates for the data structure and see if they make sense. A hex dump would be useful here.
1b. If you can see recognisable bits in the data (like your name) then look at the bytes around it to see if they make any sense, e.g. is the preceding byte, short, or long value the length of the string?
1c. Anything else that might help break the code (this is not unlike cracking weak encryption).
2. If you match the structure and it has a name then search for a wrapper that can handle that data structure.
3. Failing 2. write one yourself.

You are still at step 1 and the road is rocky.

Hi ChrisW67 thank you for your time.
I can see something readable in the c# code after a byte to ascii conversion.
So I think I should do the same in QT

wysota
23rd April 2010, 03:06
If for you is so hard to give some line of "pseudo code" as administrators of a programming forum or experts ( or Masters of Zen ) should do, so I didn't undersand the meaning of a programming forum
Ask people around - we tend to give fishing rods, not fish here.


or maybe you're jealous of your knowledge.
Don't worry, I'm not. I get much satisfaction out of helping others but you and I may understand "help" differently.


Personally when someon ask for my help in my work I'm very happy to help him as I can.
Yeah, well... if someone does the same mistake 9 times being warned about it each and every time, he might not get warned when he tries it the 10th time.


Personally I'm an hardware designer and I don't love programming gui so for me is a big effort to come here and ask for something, do you think I'm having fun coming here and write post after post to get nothing?
You are not getting nothing. You are simply not getting a ready solution. Why? See my first sentence of this post. I won't even get into the topic whether you problem is even remotely related to "programming GUI".


Is very frustrated and personally you can change my programming level to beginner or intermediate.
I'd like to change your programming level the other way round but to be honest, you're not helping and this is what is frustrating. And it should be frustrating for you too because currently you seem to be running in circles.

As I'm having a sleepless night again, I took some time to find links you might find helpful in your task:
http://www.daniweb.com/forums/thread8306.html#
http://www.roblocher.com/whitepapers/oletypes.aspx
http://edn.embarcadero.com/article/22016
http://stackoverflow.com/questions/1036720/how-to-return-list-from-c-and-use-it-in-vc-through-com
http://www.cplusplus.com/forum/beginner/8905/
http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.ole.interop.safearray.aspx
http://msdn.microsoft.com/en-us/library/cc237826%28PROT.13%29.aspx
http://www.devx.com/vb2themax/Tip/19167 (this one is in VB but you can see here how to navigate the array)

franco.amato
23rd April 2010, 03:14
Thank you wysota

franco.amato
23rd April 2010, 18:25
1. Determine what the data structure actually is. My best guess is in post #37 and its content may be a serialised C# object.
1a. Match bytes from the byte array against candidates for the data structure and see if they make sense. A hex dump would be useful here.
1b. If you can see recognisable bits in the data (like your name) then look at the bytes around it to see if they make any sense, e.g. is the preceding byte, short, or long value the length of the string?
1c. Anything else that might help break the code (this is not unlike cracking weak encryption).
2. If you match the structure and it has a name then search for a wrapper that can handle that data structure.
3. Failing 2. write one yourself.

You are still at step 1 and the road is rocky.

Hi I got the data structure from the constructor.
There still is something I don't understand. Why I need to convert to hex? I did it and noticed tha the size is changed. It's twice respect the original bytearray:


ba = m_axobj->dynamicCall("GetUserData(QString)", "1234567890" ).toByteArray(); //<-- size 441
QByteArray baHex = ba.toHex(); //<-- size 882

wysota
23rd April 2010, 18:41
You were supposed to print it on the screen to see what is inside. Though I still think an ascii dump would be better if the structure holds mostly character-based content.

franco.amato
23rd April 2010, 18:59
You were supposed to print it on the screen to see what is inside. Though I still think an ascii dump would be better if the structure holds mostly character-based content.

I'll write a byte-to-ascii converter.
The structure contains both character-based content (as name and surname) and not character-based ( as finger print data )
Meanwhile my final goal is to parse the byte array and pack another structure to write back to another finger print terminal

franco.amato
23rd April 2010, 21:20
I'll write a byte-to-ascii converter.
The structure contains both character-based content (as name and surname) and not character-based ( as finger print data )
Meanwhile my final goal is to parse the byte array and pack another structure to write back to another finger print terminal

Hi,
how could I do for example to read the first 4 bytes of the bytearray data and convert them to an integer?
I have to copy with the memcpy?

wysota
23rd April 2010, 22:01
It depends on the byte order of the architecture but memcpy will work too.

franco.amato
23rd April 2010, 22:04
It depends on the byte order of the architecture.

Hi wysota, could you do more specific?
I would convert the first 4 bytes of the bytearray in a number, the cardId in my case that it's a number of maximum 10 digits and that I can represent with 4 bytes.
I tried this



QByteArray ba;
ba = m_axobj->dynamicCall("GetUserData(QString)", "1234567890" ).toByteArray();
QByteArray cardId = ba.left(4); //now cardId contains the first 4 bytes of ba
qint32 v = qFromBigEndian( (const uchar*)cardId.constData() );


without success.
Where I'm wrong?

wysota
23rd April 2010, 22:30
Hi wysota, could you do more specific?
It depends whether the architecture is big-endian or little-endian.





int size = ba.size();
QByteArray cardId = ba.left(4); //now cardId contains the first 4 bytes of ba
qint32 v = qFromBigEndian( (const uchar*)cardId.constData() );


without success.
Maybe your machine is little-endian.

franco.amato
23rd April 2010, 22:36
It depends whether the architecture is big-endian or little-endian.


Maybe your machine is little-endian.

wysota, the problem is in compilation. Compiler says I cannot convert from 'const unsigned char *' to 'qint32'

so I changed

qint32 v = qFromBigEndian( (const uchar*)cardId.constData() );

to

qint32 v = qFromBigEndian( (const uchar*)(cardId.constData()) );

for the operator precedence but nothing change.
I still get such error. This sounds strange as the documentation says
T qFromBigEndian ( const uchar * src )
where T can be a qint32

ChrisW67
23rd April 2010, 22:52
Why I need to convert to hex? I did it and noticed that the size is changed.

Google Hexadecimal. Seriously. If you printed each byte out in decimal you'd expect the size to be different... hex is just another human readable format that's longer than what it represents.

There were clearly a good number of non-printable characters in the 441 byte data block. Just looking at the gibberish printed doesn't concretely tell you that the printed sequence "I??" is actually a series of bytes with decimal values: 49, 63, 2, 20 (example only). The "?" characters might be the result of a byte matching the ASCII for "?" (first one) or a byte that matches nothing the machine can print so it substitutes a "?" (the second). Dumping the bytes as a series of decimal or hexadecimal values allows you to see the actual values of the bytes. Hex was easier because there's already method to do that.

I agree with Wysota that straight character dump is also needed.


how could I do for example to read the first 4 bytes of the bytearray data and convert them to an integer?

Think about how four bytes are arranged into a 32-bit integer. Extract the four bytes and combine them. Also think about what order the four bytes may be in the data stream versus what order they may be in your 32-bit integer. Search for "Endianness". You could also try casting a pointer to the byte array's data block but that has downsides.

franco.amato
23rd April 2010, 22:56
I agree with Wysota that straight character dump is also needed.
what does mean?


Think about how four bytes are arranged into a 32-bit integer. Extract the four bytes and combine them. Also think about what order the four bytes may be in the data stream versus what order they may be in your 32-bit integer. Search for "Endianness". You could also try casting a pointer to the byte array's data block but that has downsides.

I extracted and copied first 4 bytes to a new bytearray and tried to convert to a number. See post above with the code I wrote but I get a compiler error that I don't understand

wysota
23rd April 2010, 23:13
what does mean?
Please read the whole thread again and Google for every term you are not sure you understand. We have already discussed this and at the end at least I came to an impression that you implied you knew how to print the contents of the byte array in ascii. I suggest you do it now and post here the output you get as for now you are only chasing ghosts.


I extracted and copied first 4 bytes to a new bytearray and tried to convert to a number. See post above with the code I wrote but I get a compiler error that I don't understand
The compiler says you can't cast a non-mutable pointer to a charater to 32 bit signed integer. Even if you managed to do that, I doubt you would be using the value you wanted to use, especially if your machine is 64bit. It'd be best if you checked whether qFromBigEndian() actually does what you expect it to. Moreover it seems you are using Intel based Windows machine so I can hardly believe some driver would return some internal number in big-endian encoding.

franco.amato
23rd April 2010, 23:20
Please read the whole thread again and Google for every term you are not sure you understand. We have already discussed this and at the end at least I came to an impression that you implied you knew how to print the contents of the byte array in ascii. I suggest you do it now and post here the output you get as for now you are only chasing ghosts.


The compiler says you can't cast a non-mutable pointer to a charater to 32 bit signed integer. Even if you managed to do that, I doubt you would be using the value you wanted to use, especially if your machine is 64bit. It'd be best if you checked whether qFromBigEndian() actually does what you expect it to. Moreover it seems you are using Intel based Windows machine so I can hardly believe some driver would return some internal number in big-endian encoding.

Hi wysota yes my machine is little endian ( Intel ).
Meanwhile I'm trying to store the first 4 bytes (32 bits) into an integer to check the value. I should get the number 1234567890 that can be stored with 4 bytes,
but seems an impossible task for me

wysota
23rd April 2010, 23:23
I will not post any more posts in this thread until I see the hexadecimal and ascii dump (or something that at least remotely looks like one) of the byte array contents you get from the COM method.

franco.amato
23rd April 2010, 23:27
I will not post any more posts in this thread until I see the hexadecimal and ascii dump (or something that at least remotely looks like one) of the byte array contents you get from the COM method.

here the hexadecimal dump


499602d20000686f72697a6174694672616e636f0000000000 00000000416d61746f00000000000000000000010103000000 00323232323232323232323232323232632003010a04150a04 1530393837363534333231010160451710138d22554620c210 a90c144351aa861983c04f06224420a90b3204909f062845d1 a30a32468044850c4831080b1548f1b2890a496165882e89d1 9e0628cb603e862fcd703c893b4dc098a01dcdf09e883acec0 9598220f0138881e8f603a88210fe095831b50519e0d159081 04602791603288189251290affff1123333ffffffff0112333 34ffffffe011223334fffffde0112233344fffdee011223334 4fffeee01122233344ffeee01112233444ffeeee0112233444 ffddee0112233444ffddde0112333444ffcdde0122334444ff ccdd0123444445ffcccd0134445445ffbbcc02345555456fbb cc02455555556fabbbe4566666556faaaaa6666666667faaaa 977777666687f99998777776678f0000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000

wysota
23rd April 2010, 23:29
And ascii?

franco.amato
23rd April 2010, 23:36
And ascii?


"I??\0\0xml;q=0.Franco\0\0\0\0\0\0\0\0\0Amato \0\0 \0\0\0\0\0\0\0\0\0\0\0\0AAAAAAAAAAAAAAA=0\0\n \n0987654321`E?\"UF ??\fCQ????O\"D ?\v2??(E??\n2F?D?\fH1\b\vH???\nIae?.???(?`>?/?p<?;M???????:????\"8??`:?!???PQ?\r??`'?`2 ??Q)\n??#3?????#34????\"34????\"34O???\"34O? ??\"#3D???#4D???#4D???#4D???34D???\"3DD? ??#DDE???4DTE???4UUEo??EUUUo???VffUo???ffff?? ?wwff????wwvg?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0"

from the C# code

wysota
23rd April 2010, 23:45
I don't want C# code. How do you know ActiveX returns data packaged in the same way to C++ and C#?

Anyway I can tell you the first four bytes in your blob are not a number. Unless you are expecting a huge value there... like 47335830

franco.amato
23rd April 2010, 23:53
I don't want C# code. How do you know ActiveX returns data packaged in the same way to C++ and C#?

Anyway I can tell you the first four bytes in your blob are not a number. Unless you are expecting a huge value there... like 47335830

yes I'm expecting 1234567890

wysota
23rd April 2010, 23:57
In that case it's there as big endian.

franco.amato
23rd April 2010, 23:58
In that case it's there as big endian.

I didn't understand.
You found the value 1234567890 in the first 4 bytes??? Really?
If yes please help me to extract and show it as I'm becoming crazy.
Meanwhile the big endian you mentioned has sense has the stream come from a fingerprint reader that's not based on
intel cpu.

wysota
24th April 2010, 00:36
You found the value 1234567890 in the first 4 bytes??? Really?
Sure.


If yes please help me to extract and show it as I'm becoming crazy.
Take a calculator (preferably one that understands hex) and calculate it yourself from the hex dump you provided :)

Or simply ask Google - 0x499602d2 in decimal (http://www.google.com/search?q=0x499602d2 in decimal).

franco.amato
24th April 2010, 17:57
Sure.


Take a calculator (preferably one that understands hex) and calculate it yourself from the hex dump you provided :)

Or simply ask Google - 0x499602d2 in decimal (http://www.google.com/search?q=0x499602d2 in decimal).

I tried these code:


QByteArray ba = m_axobj->dynamicCall("GetUserData(QString)", myCardId ).toByteArray();

int cardIdBE = 0;
memcpy( &cardIdBE, ba, sizeof(int) );
int cardIdLE = qFromBigEndian(cardIdBE);
qDebug() << cardIdLE; //1234567890

And it returns the correct value,
thank you

wysota
24th April 2010, 18:45
You should use qint32 (or quint32 if the number is unsigned) and not int.

franco.amato
25th April 2010, 18:01
You should use qint32 (or quint32 if the number is unsigned) and not int.

Wysota how can I do to convert from bigendian some bytes of the qbytearray?
For example I would convert from bigendian the bytes from ba[14] to ba[28] ( 15 bytes ).

I did this

char* name = new char[15];
memcpy( name, &ba[14], sizeof(char)*15); //I copy 15 bytes of ba to name
char* name_converted = new char[15];
name_converted = qFromBigEndian(name);

now I would convert from bigendian the content of name to display the name.
but the qFromBigEndian doesn't return as value a char[] so I can not display correct a name

faldzip
25th April 2010, 18:13
Wysota how can I do to convert from bigendian some bytes of the qbytearray?
For example I would convert from bigendian the bytes from ba[14] to ba[28] ( 15 bytes ).

I did this

char* name = new char[15];
memcpy( name, &ba[14], sizeof(char)*15); //I copy 15 bytes of ba to name
char* name_converted = new char[15];
name_converted = qFromBigEndian(name);

now I would convert from bigendian the content of name to display the name.
but the qFromBigEndian doesn't return as value a char[] so I can not display correct a name
qFromBigEndian() is a template function and returns type given in template call.

But... Can you name a type which has a 15 bytes?? I don't know such type... they rather have 2^n bytes, so what type do you want to get?

wysota
25th April 2010, 19:41
Wysota how can I do to convert from bigendian some bytes of the qbytearray?
For example I would convert from bigendian the bytes from ba[14] to ba[28] ( 15 bytes ).

I did this

char* name = new char[15];
memcpy( name, &ba[14], sizeof(char)*15); //I copy 15 bytes of ba to name
char* name_converted = new char[15];
name_converted = qFromBigEndian(name);

now I would convert from bigendian the content of name to display the name.
but the qFromBigEndian doesn't return as value a char[] so I can not display correct a name

I think you should first learn what "big-endian" and "little-endian" actually mean and whether they have any application in this context.

franco.amato
25th April 2010, 20:49
I think you should first learn what "big-endian" and "little-endian" actually mean and whether they have any application in this context.

I know what [big-little]endian is, the bit alignment, depending of cpus.
In my case I have a processor that align in bigendian and to show the data in my pc I have to convert in littleendian

wysota
25th April 2010, 21:12
I know what [big-little]endian is,
I don't think you do.


the bit alignment, depending of cpus.
It has nothing to do with neither "bit" nor "alignment".


In my case I have a processor that align in bigendian and to show the data in my pc I have to convert in littleendian
Please, do me a favour and read about it again, because you are wrong.

franco.amato
25th April 2010, 21:20
I don't think you do.


It has nothing to do with neither "bit" nor "alignment"..

In computing, endianness is the ordering of individually addressable sub-units (words, bytes, or even bits) within a longer data word stored in external memory. From http://en.wikipedia.org/wiki/Endianness ( It has nothing to do with bit ?? alignement or ordering for me is the same )


Please, do me a favour and read about it again, because you are wrong.

Maybe my english is not perfect and I'm not able to well explain but I know what big or little endian is

wysota
25th April 2010, 22:17
alignement or ordering for me is the same
Well, maybe it's the same for you but it's not the same. And please go past what is written in wikipedia. That's a source of "information" not a source of information.


Maybe my english is not perfect and I'm not able to well explain but I know what big or little endian is
Good, let's see that. Let's assume the following data has been written on a big-endian machine:

quint32 x = 0x12345678;
const char *str = "abcd"; // remember about implicit '\0' at the end of the string
Could you please tell me how a little-endian machine would interpret values of both variables (assuming it was somehow loaded directly into its memory core)? Just please don't write a program to do it, just use your mind, all the needed data is here.

Edit: sorry, one thing that may be important is missing here - do it assuming both machines are 32bit architectures.

franco.amato
25th April 2010, 22:37
Well, maybe it's the same for you but it's not the same. And please go past what is written in wikipedia. That's a source of "information" not a source of information.


Good, let's see that. Let's assume the following data has been written on a big-endian machine:

quint32 x = 0x12345678;
const char *str = "abcd"; // remember about implicit '\0' at the end of the string
Could you please tell me how a little-endian machine would interpret values of both variables (assuming it was somehow loaded directly into its memory core)? Just please don't write a program to do it, just use your mind, all the needed data is here.

Edit: sorry, one thing that may be important is missing here - do it assuming both machines are 32bit architectures.

0x78563412 in first case and
"dcba" in second case

wysota
25th April 2010, 22:59
0x78563412 in first case and
"dcba" in second case

Are you sure? You can still change something if you want. Take your time...

franco.amato
25th April 2010, 23:11
Are you sure? You can still change something if you want. Take your time...

No I don't change. It should be so

wysota
25th April 2010, 23:25
Ok, if you say so... You are wrong, the proper answer is:

0x78563412 or 0x56781234 in first case (both forms are correct little-endian encodings, even your wikipedia article says that when you bother to read the whole article and not only the first few lines) and "abcd" in second case.

Character strings are opaque for the processor, it doesn't interpret them in any way so there is no point in manipulating the order of bytes in them hence they are always stored as "big-endian". This is very logical, because each character occupies exactly one byte so there is nothing to reverse there and subsequent characters occupy subsequent bytes in memory. Otherwise it wouldn't be possible to iterate character strings and this is where "alignment" kicks in:

quint32 array[4];
quint32 *aPtr = array;
quint32 *aPtr2 = array+1;
int diff1 = (int)(aPtr2) - (int)(aPtr);
char str[4];
char *sPtr =str;
char *sPtr2 = str+1;
int diff2 = (int)(aPtr2) - (int)(aPtr);
diff1 will equal 4 and diff2 will equal 1. ints are word-aligned, chars are byte-aligned.

Now that you have all that knowledge, go back to your problem with converting the blob from big-endian and solve it. Think whether this opaque byte array is more related to an array of ints or to an array of chars.

Just a side note - you wouldn't have to do all that if you did what I asked you to a few dozens of posts ago - dump the byte array in ascii format to the console to see what's inside it. I just suspect you don't know how to do that and are afraid to admit it because otherwise you would have done it long ago.

Edit: By the way, even assuming little-endian architectures were storing strings as you described it, your answer would still be incorrect. I told you to look out for the implicit \0 character that is at the end of the string. You answer should be "dcba"+3bytes of garbage+'\0' or '\0'+"dcba".

franco.amato
25th April 2010, 23:35
Ok, if you say so... You are wrong, the proper answer is:

0x78563412 or 0x56781234 in first case (both forms are correct little-endian encodings, even your wikipedia article says that when you bother to read the whole article and not only the first few lines) and "abcd" in second case.

Character strings are opaque for the processor, it doesn't interpret them in any way so there is no point in manipulating the order of bytes in them hence they are always stored as "big-endian". This is very logical, because each character occupies exactly one byte so there is nothing to reverse there and subsequent characters occupy subsequent bytes in memory. Otherwise it wouldn't be possible to iterate character strings and this is where "alignment" kicks in:

quint32 array[4];
quint32 *aPtr = array;
quint32 *aPtr2 = array+1;
int diff1 = (int)(aPtr2) - (int)(aPtr);
char str[4];
char *sPtr =str;
char *sPtr2 = str+1;
int diff2 = (int)(aPtr2) - (int)(aPtr);
diff1 will equal 4 and diff2 will equal 1. ints are word-aligned, chars are byte-aligned.

Now that you have all that knowledge, go back to your problem with converting the blob from big-endian and solve it. Think whether this opaque byte array is more related to an array of ints or to an array of chars.

Just a side note - you wouldn't have to do all that if you did what I asked you to a few dozens of posts ago - dump the byte array in ascii format to the console to see what's inside it. I just suspect you don't know how to do that and are afraid to admit it because otherwise you would have done it long ago.


char a;
iterate over all size() of the byte array
a = ba[i];
qDebug() << int(a)

I'm not afraid, I'm out of office and I can not access to my code/data

wysota
25th April 2010, 23:51
char a;
iterate over all size() of the byte array
a = ba[i];
qDebug() << int(a)
Hmm... what is this supposed to do? It seems it will dump the array as decimal numbers which doesn't say anything new if you already have it dumped as hex.


I'm not afraid, I'm out of office and I can not access to my code/data
I'm not in your office, I don't have access to your code nor to your data but I can make an ascii dump of your byte array at any moment based on what was written in this thread so stop having excuses to everything and start thinking. We're repeating those late-night discussions each day and you are still at ground zero.

ChrisW67
26th April 2010, 00:02
Franco. Have a look at your ASCII dump of the block of data. You are interested in 15 chars starting at a certain offset. What order are the characters in?


char* name = new char[15];
memcpy( name, &ba[14], sizeof(char)*15); //I copy 15 bytes of ba to name
char* name_converted = new char[15];
name_converted = qFromBigEndian(name);

What's in name after line 2? Why do you want to change the order of the bytes in this string?

franco.amato
26th April 2010, 00:03
qFromBigEndian() is a template function and returns type given in template call.

But... Can you name a type which has a 15 bytes?? I don't know such type... they rather have 2^n bytes, so what type do you want to get?

I only would convert an undefined number of bytes

wysota
26th April 2010, 00:08
What's in name after line 2? Why do you want to change the order of the bytes in this string?
He doesn't even have to copy the data, C semantics of character strings is very useful here.


QByteArray ba = ...
const char *dat = ba.constData();
const char *name = dat+14; // or strdup(dat+14) if one wants to have an own copy
printf("NAME: %s\n", name);

franco.amato
26th April 2010, 00:08
Franco. Have a look at your ASCII dump of the block of data. You are interested in 15 chars starting at a certain offset. What order are the characters in?


char* name = new char[15];
memcpy( name, &ba[14], sizeof(char)*15); //I copy 15 bytes of ba to name
char* name_converted = new char[15];
name_converted = qFromBigEndian(name);

What's in name after line 2? Why do you want to change the order of the bytes in this string?

Dear Chris,
my stream of bytes come from a fingerprint reader that order bytes using bigendian order.
So I read data and to process them I have to first convert to little endian to understand it.
Wysota told that character strings doen't matter so I have to change the order of the rest of my stream

wysota
26th April 2010, 00:11
Wysota told that character strings doen't matter so I have to change the order of the rest of my stream
You don't have to change anything unless you know a specific subset of bytes holds an integer. Most of your array is obviously character based. Extract all required data, dump it to the console and convert only that which is wrong.

faldzip
26th April 2010, 08:35
I can't understand why franco wants to apply endianess to arrays?


#include <iostream>

int main()
{
unsigned int a = 0x12345678;
char b[4] = { 0x12, 0x34, 0x56, 0x78 };
unsigned int *c = (unsigned int *)b;
std::cout << " a = " << std::hex << a << std::endl;
std::cout << "*c = " << std::hex << *c << std::endl;
return 0;
}

What would be shown on the screen dependently on edianess?

wysota
26th April 2010, 09:29
I can't understand why franco wants to apply endianess to arrays?
That makes three of us now :)

franco.amato
26th April 2010, 21:55
That makes three of us now :)

Very well 3 of you!!!!
Well, I would convert some bytes of a QByteArray into a QString containing value that must be converted from a hex representation so:


QByteArray ba = ..bla bla
QByteArray wtStart = ba.mid(47, 2); // I extract 2 bytes containing a hour (should be 08:15)
QByteArray wtsHex = wtStart.toHex(); //dump to hex format now wtsHex contain (080f)
QString b(wtsHex); // b contains "080f" but I would it contains 0815 that's an hour 08:15.

Is there a way to do it of I have to manually convert it?

Regards

ChrisW67
27th April 2010, 01:05
It looks to me like the sender has chosen to encode a time of day as two independent bytes. The first byte is the hour (presumably 0 to 23) and the second byte is the minute (0 to 59). You can get what you want by using each byte independently: in your case the first byte is 8, the second is 15 (or 0x0F). I would suggest using a QString format and the QString::arg() method twice.

franco.amato
27th April 2010, 02:33
It looks to me like the sender has chosen to encode a time of day as two independent bytes.
Yes it's so.


The first byte is the hour (presumably 0 to 23) and the second byte is the minute (0 to 59). You can get what you want by using each byte independently: in your case the first byte is 8, the second is 15 (or 0x0F). I would suggest using a QString format and the QString::arg() method twice.

Thank you. I'll try your suggestion

faldzip
27th April 2010, 09:34
Very well 3 of you!!!!
Well, I would convert some bytes of a QByteArray into a QString containing value that must be converted from a hex representation so:


QByteArray ba = ..bla bla
QByteArray wtStart = ba.mid(47, 2); // I extract 2 bytes containing a hour (should be 08:15)
QByteArray wtsHex = wtStart.toHex(); //dump to hex format now wtsHex contain (080f)
QString b(wtsHex); // b contains "080f" but I would it contains 0815 that's an hour 08:15.

Is there a way to do it of I have to manually convert it?

Regards

Your code does not make any sense for me. I think that opening 2 tabs in Assistant (QByteArray, QTime) and just using brain for 5 to 10mins (10 is too much but I can understand it) can give you a solution. Why are you asking us for almost any smallest issue which is even not connected with any Qt specific features, those issues just requires you to think for a while about the problem or sometimes to also read about some basics like endianess, where google is your friend and can give you answer in 1s - so you can get the answer for some question faster than even writing this question on forum (any forum, not only Qt Centre).
I really want to help people here on Qt Centre, but for example: when I am helping my younger brother to do his first C++ projects for his studies, I don't give you straight solution, I just want him to think for a while as I'm giving only hints so finally he discovers right solution by himself with a little help, so when he faces similar solution to days later then he knows those basic steps leading him to the right solution. He knows he can use www.cppreference.com or google for some specific, detailed explanations.

But you look like don't know that google and Qt Assistant exist. You look like you rather want to spend 5minutes on writing new post and waiting minutes to hours for answer than just spending those 5 minutes on finding the solution...
Why can't you learn that you need to know some basic stuff to understand some more complex, as usually this complex stuff is explained with those basics?
Why can't you learn that "alignment" and "ordering" is not the same especially when you talk about endianess?
You just want to jump over the problems to get the working code fast. If you want so, then maybe you should ask someone to do the job for you and pay him for his job?

franco.amato
27th April 2010, 18:13
Your code does not make any sense for me. I think that opening 2 tabs in Assistant (QByteArray, QTime) and just using brain for 5 to 10mins (10 is too much but I can understand it) can give you a solution. Why are you asking us for almost any smallest issue which is even not connected with any Qt specific features, those issues just requires you to think for a while about the problem or sometimes to also read about some basics like endianess, where google is your friend and can give you answer in 1s - so you can get the answer for some question faster than even writing this question on forum (any forum, not only Qt Centre).
I really want to help people here on Qt Centre, but for example: when I am helping my younger brother to do his first C++ projects for his studies, I don't give you straight solution, I just want him to think for a while as I'm giving only hints so finally he discovers right solution by himself with a little help, so when he faces similar solution to days later then he knows those basic steps leading him to the right solution. He knows he can use www.cppreference.com or google for some specific, detailed explanations.

But you look like don't know that google and Qt Assistant exist. You look like you rather want to spend 5minutes on writing new post and waiting minutes to hours for answer than just spending those 5 minutes on finding the solution...
Why can't you learn that you need to know some basic stuff to understand some more complex, as usually this complex stuff is explained with those basics?
Why can't you learn that "alignment" and "ordering" is not the same especially when you talk about endianess?
You just want to jump over the problems to get the working code fast. If you want so, then maybe you should ask someone to do the job for you and pay him for his job?

Dear faldżip,
I don't need another father as I already have Wysota that likes doing sermons.
Convert content bytes of a QString from exadecimal to other format is a Qt related stuff or not?
I already got the answer from ChrisW67 that suggested to convert byte to byte and that's not possible to convert all the content, so please don't loose your time to write sermons as wysota always does.
If you don't want reply to my question or if you think you are a superman thinking that other persons don't use their brain, please simply don't reply so you can have more time to help your younger brother.
I know assistant and google, and if I ask something here if because I can not solve it.
Another thing: I don't need to convert a value to a time, I simply need to convert a hex value to a decimal value, so maybe you didn't well read my question, seems that I'm not the only that must turn on his brain :cool:

Meanwhile thank you for the time you spent and alignment and ordering for my poor english vocabulary is the same, the important is the concept not the world or you also would criticize my english skill?

franco.amato
27th April 2010, 20:04
Your code does not make any sense for me. I think that opening 2 tabs in Assistant (QByteArray, QTime) and just using brain for 5 to 10mins (10 is too much but I can understand it) can give you a solution. Why are you asking us for almost any smallest issue which is even not connected with any Qt specific features, those issues just requires you to think for a while about the problem or sometimes to also read about some basics like endianess, where google is your friend and can give you answer in 1s - so you can get the answer for some question faster than even writing this question on forum (any forum, not only Qt Centre).
I really want to help people here on Qt Centre, but for example: when I am helping my younger brother to do his first C++ projects for his studies, I don't give you straight solution, I just want him to think for a while as I'm giving only hints so finally he discovers right solution by himself with a little help, so when he faces similar solution to days later then he knows those basic steps leading him to the right solution. He knows he can use www.cppreference.com or google for some specific, detailed explanations.

But you look like don't know that google and Qt Assistant exist. You look like you rather want to spend 5minutes on writing new post and waiting minutes to hours for answer than just spending those 5 minutes on finding the solution...
Why can't you learn that you need to know some basic stuff to understand some more complex, as usually this complex stuff is explained with those basics?
Why can't you learn that "alignment" and "ordering" is not the same especially when you talk about endianess?
You just want to jump over the problems to get the working code fast. If you want so, then maybe you should ask someone to do the job for you and pay him for his job?

faldżip I wrote this code to achieve my goal:


QByteArray wtStart = ba.mid(47, 2);
QByteArray wtsHex = wtStart.toHex();
QString str(wtsHex);
QString ora_s = str.left(2);
QString min_s = str.right(2);
QString oraInizio;

bool ok;
oraInizio = QString::number( ora_s.toShort(&ok, 16), 10 );
oraInizio += QString::number( min_s.toShort(&ok, 16), 10 );

now oraInizio contains 0815 that's exactly what I wanted. I'm sure is not the fastest way but I'm not a superman as you.
Do you see the needed of the QTime here?

wysota
27th April 2010, 20:07
Dear faldżip,
I don't need another father as I already have Wysota that likes doing sermons.
(...)
I already got the answer from ChrisW67 that suggested to convert byte to byte and that's not possible to convert all the content, so please don't loose your time to write sermons as wysota always does.
I would suggest that you avoid being so personal. Remember we are all helping you out of good will and if you act in an annoying way you risk that we turn our attention elsewhere where our help is more appreciated.

As for your English skills remember it is you who has to formulate the problem clearly and it is only your responsibility if anybody else misunderstands what you say. "Alignment" and "order" have very different meanings when it comes to processors (and you as a 'hardware designer' should be aware of that) and I'm sure any decent dictionary would agree with me. So don't blame others for trying to help you and start thinking whether you could have done more yourself.

If you don't want my technical advice, you won't receive it but I'm still a moderator on this forum and I kindly ask you to behave yourself and appreciate that others devote their time to trying to help you. It is a very rare case that I remind someone I have means of enforcing order here so treat it as a serious warning. I will probably not use my power because I think I may not be objective in this caase but I might ask other moderators to take a closer look at this thread.

franco.amato
27th April 2010, 20:19
I would suggest that you avoid being so personal. Remember we are all helping you out of good will and if you act in an annoying way you risk that we turn our attention elsewhere where our help is more appreciated.

As for your English skills remember it is you who has to formulate the problem clearly and it is only your responsibility if anybody else misunderstands what you say. "Alignment" and "order" have very different meanings when it comes to processors (and you as a 'hardware designer' should be aware of that) and I'm sure any decent dictionary would agree with me. So don't blame others for trying to help you and start thinking whether you could have done more yourself.

If you don't want my technical advice, you won't receive it but I'm still a moderator on this forum and I kindly ask you to behave yourself and appreciate that others devote their time to trying to help you. It is a very rare case that I remind someone I have means of enforcing order here so treat it as a serious warning. I will probably not use my power because I think I may not be objective in this caase but I might ask other moderators to take a closer look at this thread.

Wysota your're right,
but sincerely I'm a bit tired to listen things as "use your brain", I very appreciate your help but you also should understand people that doesn't have your [Qt, c++] knoledge level.
Every time I don't understand something or everytime something doesn't work I before search on internet, or in the forum, online books and so on, and only when I can not solve it I ask here.
Now forget the reference to "wysota" in my last post (only was a joke), but faldżip should not think that people are foo and that don't use their brain at work.
Please appreciate my apology.

Regards

wysota
27th April 2010, 20:40
but sincerely I'm a bit tired to listen things as "use your brain", I very appreciate your help but you also should understand people that doesn't have your [Qt, c++] knoledge level.
Franco,

when I started helping people solve their Qt problems, my Qt knowledge was exactly zero and my C++ skills were not much better. All my experience comes from dealing with problems I knew nothing about and "using my brain" and curiosity (or urge) to gain more knowledge. If I waited for others to present me with ready solutions, I wouldn't have learned anything. If you want to improve, you have to gain 95% of the knowledge on your own and only the remaining five by asking others. Take a step back and see for yourself - your problem has nothing to do with Qt or even with C++. The fact that C++ and Qt are your tools is completely meaningless because in my point of view your main issue is that it is hard for you to find solutions to problems on your own - without Internet, books or other people.

Your appology is not required (though appreciated) as I don't feel offended. I just don't want to risk you discouraging people who are willing to share their own knowledge and experience, like Filip (faldżip).

ChrisW67
27th April 2010, 22:45
faldżip I wrote this code to achieve my goal:


QByteArray wtStart = ba.mid(47, 2);
QByteArray wtsHex = wtStart.toHex();
QString str(wtsHex);
QString ora_s = str.left(2);
QString min_s = str.right(2);
QString oraInizio;

bool ok;
oraInizio = QString::number( ora_s.toShort(&ok, 16), 10 );
oraInizio += QString::number( min_s.toShort(&ok, 16), 10 );

now oraInizio contains 0815 that's exactly what I wanted. I'm sure is not the fastest way but I'm not a superman as you.
Do you see the needed of the QTime here?

There is more than one way to do these things. Some more complicated than others, and some with slightly different results. For example, your code converts two bytes to hex, pulls the hex string apart, and converts the hex strings back to decimal. Far more direct approaches exist:


QString oraInizio = QString("%1%2")
.arg(ba.at(47), 2, 10, QLatin1Char('0'))
.arg(ba.at(48), 2, 10, QLatin1Char('0'));
This also gives a leading 0 on the hours and minutes (I am not sure your solution does).

You could use QTime to achieve this goal. Something like:

QTime time( ba.at(47), ba.at(48), 0, 0);
// and to make your string from it...
QString oraInizio = time.toString("HHMM");Using QTime has the advantage that it can do validation ( QTime::isValid() ), interval mathematics (QTime::secsTo()), or ouput several different formats (QTime::toString()).

(Both code examples untested... not at my Qt machine)

SixDegrees
27th April 2010, 22:56
Dear faldżip,

Convert content bytes of a QString from exadecimal to other format is a Qt related stuff or not?



No, it's not. This is basic, fundamental, first-semester computer science.

You're asking very basic questions in a very specialized forum. You should go elsewhere and master the basics. The knowledge of those contributing to this forum is wasted until you comprehend the fundamentals.

wysota
28th April 2010, 01:36
The knowledge of those contributing to this forum is wasted until you comprehend the fundamentals.
Naah... maybe not wasted... but certainly not used in full either.

franco.amato
28th April 2010, 02:43
Naah... maybe not wasted... but certainly not used in full either.

Thank you wysota

franco.amato
28th April 2010, 02:44
There is more than one way to do these things. Some more complicated than others, and some with slightly different results. For example, your code converts two bytes to hex, pulls the hex string apart, and converts the hex strings back to decimal. Far more direct approaches exist:


QString oraInizio = QString("%1%2")
.arg(ba.at(47), 2, 10, QLatin1Char('0'))
.arg(ba.at(48), 2, 10, QLatin1Char('0'));
This also gives a leading 0 on the hours and minutes (I am not sure your solution does).

You could use QTime to achieve this goal. Something like:

QTime time( ba.at(47), ba.at(48), 0, 0);
// and to make your string from it...
QString oraInizio = time.toString("HHMM");Using QTime has the advantage that it can do validation ( QTime::isValid() ), interval mathematics (QTime::secsTo()), or ouput several different formats (QTime::toString()).

(Both code examples untested... not at my Qt machine)

Many thanx, now it's all more clear

faldzip
28th April 2010, 07:26
Convert content bytes of a QString from exadecimal to other format is a Qt related stuff or not?

The thing is that any hexadecimal numbers are not needed at all here and your problem is (was?) to convert 2 bytes containing hours and minutes to some string.


You could use QTime to achieve this goal. Something like:


QTime time( ba.at(47), ba.at(48), 0, 0);
// and to make your string from it...
QString oraInizio = time.toString("HHMM");

Using QTime has the advantage that it can do validation ( QTime::isValid() ), interval mathematics (QTime::secsTo()), or ouput several different formats (QTime::toString()).

That is why suggested using QTime (it can be useful in case of further processing of this time you get). If you would bother to read Qt Docs next time, you would know this before Chris gave the exact solution which you can simply copy and paste - I'm almost sure that you still don't know what those two '0' in QTime constructor's call means. And you probably won't read the docs to get know that you don't have to write them there.

wysota
28th April 2010, 08:48
Filip, let's drop the "Luke, I am your father" part of the discussion please.

franco.amato
28th April 2010, 17:21
I'm almost sure that you still don't know what those two '0' in QTime constructor's call means.

Seconds and mseconds.


And you probably won't read the docs to get know that you don't have to write them there.

Because there is a default value set.
Don't be so sure please!

faldzip
28th April 2010, 21:11
Seconds and mseconds.

Because there is a default value set.
Don't be so sure please!
Nice to hear it :]