GeorgeG Posted January 30, 2012 Report Share Posted January 30, 2012 I have a class hierarchy something like top-level-class, which has no children, but contains an array of worker-class objects. There are about ten specific types of worker-class, all children of parent-class. The array usually only has a few types in it at any given time. Now I want to save top-level-class to a file. I have tried flattening to xml and saving as well as just using the write binary primitive. In both cases I get the same result. Everything is fine and dandy in the Dev environment, but fails in the build application when I try to read the file from disk. I get: Error 1403 occurred at Read from Binary File LabVIEW: Attempted to read flattened data of a LabVIEW class. The data is corrupt. LabVIEW could not interpret the data as any valid flattened LabVIEW class. In my build spec, I have everything in the project (except top-level.vi) in Always Included (under Source Files). top-level.vi is the startup file. I am at a bit of a loss how to proceed. Has anyone encountered this or have an idea where I might have gone wrong? George Quote Link to comment
Jon Kokott Posted January 30, 2012 Report Share Posted January 30, 2012 Are all the classes loaded into memory before you read the file? Quote Link to comment
GeorgeG Posted January 30, 2012 Author Report Share Posted January 30, 2012 That is a good question. No, I don't think they are. The specific worker-class children don't have any constants or controls/indicators anywhere in the application. The files are generated by a different application (but part of the same project). What is a good way to load them all into memory before reading the file? Quote Link to comment
Jon Kokott Posted January 30, 2012 Report Share Posted January 30, 2012 I just put a constant down and wire it to the get default path primative. Its helpful to see where its being loaded from to make sure its using the ones compiled into the application. I've actually been messing around with this technique a little bit; I'm not sure its a great idea to be compiling 2 disk copies. It would be better to have a packed library with the child classes (although this introduces a whole new set of issues in maintenance and understand-ability) There really should only be one copy of the compiled code in the run time environment at a time. Quote Link to comment
Jeffrey Habets Posted January 30, 2012 Report Share Posted January 30, 2012 I do the loading of a class from one of the methods, basically I 'construct' the class from file. So I have e.g. a Load method for constructing a class+data from a file and a New method for constructing it without data (or whatever the New method needs to do to initialize the data, which in my case is nothing). Since the class' load method is called, it will for sure be present in the exe, as well as the classes it aggregates (Channel in my case). Works fine here. Quote Link to comment
jgcode Posted January 30, 2012 Report Share Posted January 30, 2012 I do the loading of a class from one of the methods I like to do that too. Quote Link to comment
Aristos Queue Posted January 31, 2012 Report Share Posted January 31, 2012 You wont get 1403 from a class not in memory problem. 1403 only occurs when you flatten an object of class XYZ to a string, then try to unflatten that string using a completely unrelated XYZ class -- like flattening an XYZ that contains an integer and then unflattening with an XYZ that contains a string, and not a different version of the class, but one where we try to interpret that integer as the length bytes of the string and realize we don't have enough bytes in the flattened string to represent a string of that size. I don't know exactly what you're doing, but my first bet would be cross-linking of some sort. In other words, the class that you're using during development is *not* the same class that you're loading in your built application. Quote Link to comment
GeorgeG Posted January 31, 2012 Author Report Share Posted January 31, 2012 This works in the development environment, but fails with error 1403 after it is build into an application. Add class constants for WorkerA and WorkerB to the diagram of "UseFile" and the application will run without errors. So it does seem to be a class not in memory problem, but putting constants on the actual block diagram is not a solution I like, since there are lots of worker classes, and I will add new ones regularly. Quote Link to comment
GeorgeG Posted January 31, 2012 Author Report Share Posted January 31, 2012 Well, I am pretty sure it is a simple class not in memory problem. Pity LabVIEW didn't offer that in the error message in the first place. Anyway, getting the classes loaded seemed trickier than I thought it would be. So maybe there is a better way? My solution was to add a pre-build action to store the relative paths to the worker classes. Then the application can use that information to dynamically load all of the worker classes before it does anything else. Pre-Build Action: Changes to top level vi: 1 Quote Link to comment
TailOfGon Posted October 15, 2013 Report Share Posted October 15, 2013 I experienced the exactly same problem today. Loading classes fixed the problem. Quote Link to comment
John Lokanis Posted October 12, 2015 Report Share Posted October 12, 2015 Just bringing this thread back from the past. I ran into this exact same issue in LV2015. Here are some details: Sending a message from app1 to app2. Message payload is a class with some data members also being objects (composition). Everything was working fine in IDE and EXE. Changed one of the data members from a 2D array to an array of objects with the following structure: Parent class with abstract methods. Two child classes with concrete methods. Two grandchildren classes with different private data than one of the child classes. (the grandchildren only inherit from one of the children to specify some finer details for that branch in the tree). sending message from app1 to app2 in the IDE continues to work fine. Build both EXEs and suddenly error 1403 rears it's ugly head. After much work trying to get to the bottom of this, I find this post. I place a static copy of the child and grandchild classes on the BD of the top level VI in the app2 EXE. Problem solved! Oh, and I never called any flatten functions when sending my message. Instead I am calling a VI in app2 from app1 using call by reference node. (This VI puts the message object in the receiver's queue.) So, apparently, the call by reference node uses the flatten/unflatten object function under the hood. And also, that function has no problem resolving the class type in the IDE but fails in an EXE. I have ensured that app2 has all the classes in it's project and they are even marked 'always include' in the app builder. So, they are in the EXE but maybe not in memory already. Still, it should be able to find them and unflatten the data without the static links I had to add. And in any case, this error message is extremely misleading because there is no corruption happening. The RTE just cannot find the class definition. I hope that a CAR can be created to finally address this situation. And I hope future versions of LabVIEW can do a better job of reporting the correct error. Even better would be a version of LabVIEW where code ran the same way in an EXE as it does in the IDE. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.