LAVA Forums Buy cool LAVA gear Forums RSS Feed

Welcome Guest ( Log In | Register )

> Related links

Check out our OOP Code Repository Files or visit the LabVIEW Wiki OOP Portal.


Tags
(This content has not been tagged yet)
 
Reply to this topic Start new topic
> Flattened LVOOP Class
Eugen Graf
post Jun 24 2008, 09:52 PM
Post #1


Extremely Active
****

Member
Posts: 361
Joined: 6-February 07
From: Homburg/Germany
Member No.: 7689
Using LabVIEW Since:2004
LV:8.5 ,8.0.1 ,.
Germany Kazakhstan Russia My Gallery


Hello LAVAs!

I want know if it's possible to flatten a LVOOP Class to a binary string from e.g. C++, so I can unflatten them in LabVIEW to a LVOOP Class ?

Thanks, Eugen

--------------------


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Ad
post Jun 24 2008, 09:52 PM
Post #















Tags
(This content has not been tagged yet)
Go to the top of the page
Quote Post
ragglefrock
post Jun 24 2008, 10:03 PM
Post #2


Very Active
***

Member
Posts: 66
Joined: 1-June 06
Member No.: 5171
LV:8.0 ,. ,.
Nothing Selected Nothing Selected Nothing Selected


QUOTE (Eugen Graf @ Jun 24 2008, 04:52 PM) *
Hello LAVAs!

I want know if it's possible to flatten a LVOOP Class to a binary string from e.g. C++, so I can unflatten them in LabVIEW to a LVOOP Class ?

Thanks, Eugen


The question's a little confusing. How are you using your LVOOP class in C++? Are you calling a LabVIEW-built DLL that creates and uses LVOOP classes?

To flatten the LVOOP class appropriately, you will need to use the LabVIEW Flatten to String function. You can create a wrapper VI that calls this function with a class input and create an exported DLL function to call this from C++.


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Eugen Graf
post Jun 24 2008, 10:08 PM
Post #3


Extremely Active
****

Member
Posts: 361
Joined: 6-February 07
From: Homburg/Germany
Member No.: 7689
Using LabVIEW Since:2004
LV:8.5 ,8.0.1 ,.
Germany Kazakhstan Russia My Gallery


QUOTE (ragglefrock @ Jun 25 2008, 12:03 AM) *
The question's a little confusing. How are you using your LVOOP class in C++? Are you calling a LabVIEW-built DLL that creates and uses LVOOP classes?

To flatten the LVOOP class appropriately, you will need to use the LabVIEW Flatten to String function. You can create a wrapper VI that calls this function with a class input and create an exported DLL function to call this from C++.



I think to create a structure (=cluster) in C++ with all elements what LVOOP Class Contol Cluster has, than cast them to binary string (or byte array) and send over TCP/IP.

This post has been edited by Eugen Graf: Jun 24 2008, 10:13 PM
Attached image(s)
Attached Image
 

--------------------


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Aristos Queue
post Jun 25 2008, 01:36 AM
Post #4


LV R&D Envoy
*****

NI
Posts: 1226
Joined: 15-August 06
From: Austin, TX
Member No.: 5877
Using LabVIEW Since:2000
LV:8.5.1 ,. ,.
United States Nothing Selected Nothing Selected My Gallery


QUOTE (Eugen Graf @ Jun 24 2008, 05:08 PM) *
I think to create a structure (=cluster) in C++ with all elements what LVOOP Class Contol Cluster has, than cast them to binary string (or byte array) and send over TCP/IP.


You can create a flattened cluster string in C++ and then write a custom unflatten routine for your class that can parse the string and populate the fields of your class. But if you want to use the Unflatten From String primitive, then you'll have to format the data like a LabVIEW class gets flattened.

What does an LVClass look like when we flatten it? The string has four parts:

  1. "NumLevels" The first 4 bytes represent a uInt32. This tells us how many levels of the hierarchy are recorded herein. If NumLevels is zero, absolutely nothing else follows. Zero indicates that this is an instance of LabVIEW Object, the ancestor of all classes which has no fields, no methods and inherits ex nihilo.
  2. "ClassName". The next several bytes represent a PStr (aka Pascal String, which is a single byte that is the length of the string followed by the text of the string). This tells us the name of the class that flattened this data. This is the fully qualified name of the class, using the colon : as the delimiter character. Note that there are enough pad bytes after the PStr to get the length of the string to be a multiple of four.
  3. "VersionList". The next series of uInt16s that represent a list of version numbers. Each version number is 4 uInt16s, usually written in the format W.X.Y.Z, where W, X, Y and Z are each a uInt16. There are NumLevels of version numbers. The first version number is the version of ClassName class, followed by the version number for ClassName's parent, and so on to the version of the oldest ancestor (not including LabVIEW Object).

    SPECIAL CASE: If NumLevels == 1 and the version == 0.0.0.0, then this is the default data of the class. Skip section 4 -- no further data follows in this special case. If version is zero for any other value of NumLevels, the string is considered corrupt and the unflatten functions will return an error.
  4. "ClusterData" -- This is a series of flattened clusters, one for each level of the hierarchy. The first cluster is the oldest ancestor class. Pay attention: The version numbers start at the descendant class and go up the hierarchy. The cluster data starts at the oldest ancestor and goes down the hierarchy. Each block of data starts with 4 bytes interpreted as an int32. This int32 represents the number of bytes in the data that follows. If this number is zero, then we use the default default data for this level of the hierarchy. If this number is non-zero then this is the standard flat data representation for the cluster at this level of the inheritance hierarchy. After each cluster there are enough pad bytes to get the length of the string back to a multiple of four.

Here, for example, is a flattened class object (I put the string into slash notation to make this "easier" to parse):
CODE
\00\00\00\02\12\10Bacteria.lvclass\00\00\00\05\00\06\00\07\00\b\00\01\00\00\00\00\00\t\00\00\00\00\00\00\00\f\00\00\00\04abcd\00\00\00\00

and here is the exact same string in hex because slashcodes can be confusing:
CODE
0000 0002 1210 4261 6374 6572 6961 2E6C 7663 6C61 7373 0000 0005 0006 0007 0008 0001 0000 0000 0009 0000 0000 0000 000C 0000 0004 6162 6364 0000 0000

The first 4 bytes are NumLevels. NumLevels in this case is 2. So we have a class that has one ancestor between it and LabVIEW Object.

Next is the PStr that is the name of the class: Bacteria.lvclass. After that are 2 NULL pad bytes to get the length back to a multiple of four.

Next is the first version number: 5.6.7.8. That's the version number for Bacteria.lvclass.
Next is the second version number: 1.0.0.9. That's the version number for Bacteria's parent class. We'd have to have Bacteria in memory to ask it "Hey, who was your parent class back when you were version 5.6.7.8?"

Next come the data blocks.
The first data block has data size 0. That means that we'll just assume that the parent cluster was the default default value.
The second data block has data size 15. So the next 15 bytes are a flattened cluster of the cluster of Bacteria when it was version 5.6.7.8. Remember that the Bacteria.lvclass currently in memory might be a much later version of the class -- LabVIEW will automatically handle the conversion for you (which you can read all about here). In this case, it looks like those 15 bytes of data contain a string ("abcd") and a couple other cluster elements.

Just write code in C++ to generate this string and you can have LabVIEW unflatten it. Contrariwise, you can have LabVIEW flatten the string and you write the C++ function to parse it.

IMPORTANT NOTE: The flattened form of LabVIEW data is portable to any endian platform. We always flatten int32s, uInt32s and other data types into big endian order. If you are on a little endian machine (any Mac, Windows or Linux box is little endian), make sure that your custom write/write functions take care of reversing the bytes.

--------------------
"A VI outside a class is a gun without a safety. Data outside a class is a target."
--- A message from LabVOOP R&D


Tags
Go to the top of the page
+Quote Post
Jim Kring
post Jun 25 2008, 06:50 AM
Post #5


Changing the world, one VI at a time.
*****

JKI
Posts: 1697
Joined: 22-October 02
From: San Francisco, CA
Member No.: 17
Using LabVIEW Since:1995
LV:8.2.1 ,8.5 ,7.1.1
United States us_california Nothing Selected My Blog My Gallery


QUOTE (Aristos Queue @ Jun 24 2008, 06:36 PM) *
What does an LVClass look like when we flatten it? The string has four parts:


Great info. I've added it to the LVClass Data Storage Format wiki page. thumbup1.gif

--------------------
-----------------------------------------------------------------------------------------------------
| Book | OpenG | LAVA | Champion | VIPM | Builder | Blog | JKI |
-----------------------------------------------------------------------------------------------------


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Yair
post Jun 27 2008, 10:31 AM
Post #6


Extwemely Active
*****

Premium Member
Posts: 1632
Joined: 23-January 05
From: Here
Member No.: 1431
Using LabVIEW Since:2003
LV:8.6 ,7.0 ,.
Israel Nothing Selected Nothing Selected


Great info.

QUOTE (Aristos Queue @ Jun 25 2008, 04:36 AM) *
Here, for example, is a flattened class object (I put the string into slash notation to make this "easier" to parse):
CODE
\00\00\00\02\12\10Bacteria.lvclass\00\00\00\05\00\06\00\07\00\b\00\01\00\00\00\00\00\t\00\00\00\00\00\00\00\f\00\00\00\04abcd\00\00\00\00

Next is the PStr that is the name of the class: Bacteria.lvclass. After that are 2 NULL pad bytes to get the length back to a multiple of four.

Which of the two bytes is the PStr length, 0x12 or 0x10? Bacteria.lvclass is 16 (0x10) characters . If 0x12 is the length and 0x10 is the beginning of the string, then the string is 0x11 bytes long and needs three null characters for padding, not two. If 0x10 is the length, there shouldn't be need for padding. Or am I missing something?

QUOTE
Next is the first version number: 5.6.7.8. That's the version number for Bacteria.lvclass.
Next is the second version number: 1.0.0.11.

Are you sure you didn't switch the 8 and 11 here? In the code, \b comes in the first part and \t comes in the second.

--------------------
More than meets the eye...


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Aristos Queue
post Jun 27 2008, 11:18 AM
Post #7


LV R&D Envoy
*****

NI
Posts: 1226
Joined: 15-August 06
From: Austin, TX
Member No.: 5877
Using LabVIEW Since:2000
LV:8.5.1 ,. ,.
United States Nothing Selected Nothing Selected My Gallery


QUOTE (Yair @ Jun 27 2008, 05:31 AM) *
Which of the two bytes is the PStr length, 0x12 or 0x10? Bacteria.lvclass is 16 (0x10) characters . If 0x12 is the length and 0x10 is the beginning of the string, then the string is 0x11 bytes long and needs three null characters for padding, not two. If 0x10 is the length, there shouldn't be need for padding. Or am I missing something?
What you're missing is that I didn't fully explain how the PStr is encoded.

a) The PStr is a length byte plus the text, so that is 17 bytes, not 16, and thus padding is required.
b) The first byte, 0x12, is the total length including padding: 18
c) The second byte, 0x10, is the total length not including padding: 16
d) Thus 18 + the two length bytes = 20


QUOTE
Are you sure you didn't switch the 8 and 11 here? In the code, \b comes in the first part and \t comes in the second.
\t is the tab character, which I thought was character 11, but I checked my ascii table. Turns out it is 9. I corrected my original post. I also added the hex view for clarity. \b is not hex 11 as you thought. It's the slashcode for character 8.

--------------------
"A VI outside a class is a gun without a safety. Data outside a class is a target."
--- A message from LabVOOP R&D


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Yair
post Jun 27 2008, 11:33 AM
Post #8


Extwemely Active
*****

Premium Member
Posts: 1632
Joined: 23-January 05
From: Here
Member No.: 1431
Using LabVIEW Since:2003
LV:8.6 ,7.0 ,.
Israel Nothing Selected Nothing Selected


QUOTE (Aristos Queue @ Jun 27 2008, 02:18 PM) *
What you're missing is that I didn't fully explain how the PStr is encoded.

a) The PStr is a length byte plus the text, so that is 17 bytes, not 16, and thus padding is required.
b) The first byte, 0x12, is the total length including padding: 18
c) The second byte, 0x10, is the total length not including padding: 16
d) Thus 18 + the two length bytes = 20

Well, I still don't really understand - shouldn't the total length, including padding (step b), be 20?
Or did you mean total length including the length bytes?

What's the actual use case for having two length bytes? If you have just one length pad, you should easily be able to calculate the needed padding, shouldn't you?

QUOTE
\t is the tab character, which I thought was character 11, but I checked my ascii table. Turns out it is 9. I corrected my original post. I also added the hex view for clarity. \b is not hex 11 as you thought. It's the slashcode for character 8.

I actually had a double mix-up here. I didn't check either and thought tab was ASCII 8 and backspace is ASCII 9 (when it's the other way around). That would explain why I thought that \b is ASCII 11.

I also fixed the wiki article.

--------------------
More than meets the eye...


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
shoneill
post Jun 27 2008, 01:38 PM
Post #9


Very Active
***

Member
Posts: 173
Joined: 26-September 05
From: Zurich
Member No.: 3076
Using LabVIEW Since:2006
LV:8.2.1 ,8.20 ,6.1
Ireland Switzerland Nothing Selected


QUOTE (Yair @ Jun 27 2008, 01:33 PM) *
Well, I still don't really understand - shouldn't the total length, including padding (step b), be 20?
Or did you mean total length including the length bytes?

What's the actual use case for having two length bytes? If you have just one length pad, you should easily be able to calculate the needed padding, shouldn't you?


Seeing as the descriptors can be very long and complicated, it's very useful sometimes to know how to easily skip to the next item in the descriptor. Hence the first value.

Of course one could deduce the next offset based on the data available, but I'd rather take the 0.25 Bytes (on average) cost of the second length value for faster response time in LabVIEW.

Isn't this all derived from the general and pretty much global method of defining type descriptors? Such type descriptors for Controls can get pretty involved.

Shane.

Ps I see your point regarding the value of 18 instead of 20. I think this might also be a result of a global method of handling type descriptors IIRC. I think the descriptor for a PStr lists the total length as the total length of the DATA and thus excludes the two bytes for the size information. It will thus always be 2 Bytes short of a multiple of 4.

This post has been edited by shoneill: Jun 27 2008, 01:42 PM


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post
Aristos Queue
post Jun 28 2008, 01:23 AM
Post #10


LV R&D Envoy
*****

NI
Posts: 1226
Joined: 15-August 06
From: Austin, TX
Member No.: 5877
Using LabVIEW Since:2000
LV:8.5.1 ,. ,.
United States Nothing Selected Nothing Selected My Gallery


QUOTE (Yair @ Jun 27 2008, 06:33 AM) *
What's the actual use case for having two length bytes? If you have just one length pad, you should easily be able to calculate the needed padding, shouldn't you?
I have no idea. That's how PStrs are encoded whenever they're flattened in LabVIEW data.

--------------------
"A VI outside a class is a gun without a safety. Data outside a class is a target."
--- A message from LabVOOP R&D


Tags
(This content has not been tagged yet)
Go to the top of the page
+Quote Post

Reply to this topicStart new topic

 




Time is now: 2nd December 2008 - 04:46 AM