Stobber Posted July 2, 2012 Report Share Posted July 2, 2012 (edited) I need to get an instance of a class that I know will be loaded with my application, but "Get LV Class Default Value" seems only to work with a full on-disk path to the .lvclass file. I tried passing in a string with the fully qualified name of the class, but it gives me error 7. Is there a way to get an instance of the class on my block diagram by referencing it in memory? (This is for a generic object deserializer, so I can't simply drop a constant of the class on the block diagram.) (No, I'm not trying to reproduce AQ's work in the other thread on serialization. Although the VI I'm writing is generic, the serializer is mostly special-purpose.) Edited July 2, 2012 by Stobber 1 Quote Link to comment
Aristos Queue Posted July 2, 2012 Report Share Posted July 2, 2012 This post has the VI you're looking for: Quote Link to comment
mje Posted July 2, 2012 Report Share Posted July 2, 2012 I've run up against this too. What I wouldn't give for a more complete implementation of LabVIEW Object. There's only one way around this as far as I know: build your own look-up table. If your aware of all of the possible object types this is easy, you just need to translate an identifier to a value. If you don't have control over all the serialized types prior to distribution, you're likely going to have to roll a far more involved solution where you can register a type with a given identifier, provide a mechanism for dynamic type registration, and a factory method that spits out values for a given identifier. I keep using the generic term identifier instead of qualified name because even though a qualified name is one of the most fundamental properties of a class, we don't even have access to that, save for some hacks that are performance killers. AQ, maybe I misunderstood the question, but I think Stober needs a means of translating a qname to a value, which isn't covered in that post? Those VIs only work if you already have a value (or path)... Quote Link to comment
Stobber Posted July 2, 2012 Author Report Share Posted July 2, 2012 AQ, maybe I misunderstood the question, but I think Stober needs a means of translating a qname to a value, which isn't covered in that post? Those VIs only work if you already have a value (or path)... mje understood the question correctly. I'm storing the qualified name of the class in the string, and I want to use it to create a new object of that type when I deserialize. I looked at those Open_G VIs before posting. Maybe neither of us understands how to use them to solve this problem? Quote Link to comment
Aristos Queue Posted July 3, 2012 Report Share Posted July 3, 2012 Yeah... I misunderstood. And I've run into the same problem. I've already been working on LV 2013 to add these functions. In the meantime, I gave Staab a workaround. If it works for him, I'll let him repost it here. (an unfortunate but workable workaround for limited use cases). 1 Quote Link to comment
Stobber Posted July 3, 2012 Author Report Share Posted July 3, 2012 AQ's workaround for a deployed application (always my situation) is to add the .lvclass files to specific paths inside the built EXE, then provide a path to the class file using the Application Path primitive and a relative path inside the EXE. It doesn't actually pull an instance of the object from the application's memory space using the qualified name, but it's a workable approach since the EXE path can be obtained using a prim. To specify the location of the .lvclass file inside the EXE, add it to the "Always Included" list in the build spec, then create a "Destination" for it with the full path. For XYZ.lvclass, an example Destination Path would be C:\build\MyApp.exe\XYZ\. When you want to load an object of XYZ at run time, you provide the path C:\build\MyApp.exe\XYZ\XYZ.lvclass AQ told me that all the classes to be loaded need to be either inside the EXE or outside it; they can't be mixed. I didn't test that assertion b/c all my classes will be shipped in the built EXE. 1 Quote Link to comment
mje Posted July 3, 2012 Report Share Posted July 3, 2012 That works. I'm curious, does the default value VI do some level of caching so it does not need to go to disk on each call if the same class is requested multiple times? Quote Link to comment
Aristos Queue Posted July 3, 2012 Report Share Posted July 3, 2012 Staab: I thought of a second solution for you... you could build a Variant attribute database where the key is the name of the class and the value is the default value of the object. That does away with requirements to put the classes in a particular location in the EXE. mje: If the class is already in memory, there's no need to go back to disk on subsequent calls. The rules are the same as opening a VI reference for a VI already in memory. Quote Link to comment
Stobber Posted July 5, 2012 Author Report Share Posted July 5, 2012 Staab: I thought of a second solution for you... you could build a Variant attribute database where the key is the name of the class and the value is the default value of the object. That does away with requirements to put the classes in a particular location in the EXE. That's what mje was talking about with the "lookup table". Quote Link to comment
Aristos Queue Posted July 6, 2012 Report Share Posted July 6, 2012 That's what mje was talking about with the "lookup table". Oops. I hadn't read the rest of the thread... I was posting from my phone so I didn't forget to tell Staab that idea. Quote Link to comment
EricBehrs Posted August 1, 2012 Report Share Posted August 1, 2012 AQ's workaround for a deployed application (always my situation) is to add the .lvclass files to specific paths inside the built EXE, then provide a path to the class file using the Application Path primitive and a relative path inside the EXE. It doesn't actually pull an instance of the object from the application's memory space using the qualified name, but it's a workable approach since the EXE path can be obtained using a prim. To specify the location of the .lvclass file inside the EXE, add it to the "Always Included" list in the build spec, then create a "Destination" for it with the full path. For XYZ.lvclass, an example Destination Path would be C:\build\MyApp.exe\XYZ\. When you want to load an object of XYZ at run time, you provide the path C:\build\MyApp.exe\XYZ\XYZ.lvclass Is there any reason this method would not work in a Shared Lib DLL? I've built a test project with build specs for both an EXE output and a DLL. Both use the method described above, using the appropriate name (...\MyApp.exe\XYZ\ or ...\MyApp.dll\XYZ\) for the Destination Path. The EXE loads the class fine, but the DLL still gives Error 7 on the "Get LV Class Default Value" call. Anyone have ideas/thoughts on this one? Has anyone successfully loaded a class dynamically in a Shared Lib (from memory, not from disk)? Quote Link to comment
Stobber Posted March 13, 2013 Author Report Share Posted March 13, 2013 Update: AQ's suggested workarounds still work, but they're also still a PITA. Anybody know whether this need is met by LV2013? Quote Link to comment
Mike Le Posted April 12, 2013 Report Share Posted April 12, 2013 I just found this thread today after trying to find a solution. Would also be interested to know if LV2013 provides a simpler dynamic loading method for executables. Quote Link to comment
Mike Le Posted February 8, 2014 Report Share Posted February 8, 2014 Thought I'd give this thread another bump as I'm again jumping through the hoops to make classes load dynamically in an exe. Quote Link to comment
mje Posted February 8, 2014 Report Share Posted February 8, 2014 Though I have yet to re-write any of my VIs to use this, I think the new Get LV Class Default Value By Name VI does the trick. Qualified names of course, but there's a corresponding VI that returns those too now. 1 Quote Link to comment
CharlesB Posted May 23, 2014 Report Share Posted May 23, 2014 I'm looking for the pre-LV2013 version of this VI, that works from a FQN, does anyone have it? Quote Link to comment
CharlesB Posted May 26, 2014 Report Share Posted May 26, 2014 OK I found NI's "Class retrieval" library that does the job, in the NI Tools Network, but the minimum requirement is LV 2012, though I'd need it for 2011 It could have been a matter of saving the library to LV2011, but there are password protected VIs like "2013 Get LV Class Default Value By Name.vi". This VI is precisely aimed at using builtin 2013 functionality when run from LV2013. For now I've came up with removing this code that uses 2013's bultin VI, and always use the pre-2013 workaround. FWIW I need it for implementing class instance deserialization in the JSON API. Quote Link to comment
Stobber Posted May 26, 2014 Author Report Share Posted May 26, 2014 What's the path to the Class Retrieval library? I'd like to poke around and see what it can do! Quote Link to comment
CharlesB Posted May 26, 2014 Report Share Posted May 26, 2014 (edited) What's the path to the Class Retrieval library? I'd like to poke around and see what it can do! It's in <vi.lib>/NI/Class Retrieval/. Basically it is built around a FGV that holds a lookup table between class names and paths, and when ran from LV2013 it delegates this to the native VIs (that are password protected, since built into LabVIEW). For pre-2013, if the class isn't found in the table, it asks uses LabVIEW's project introspection to find it, so your classes just have to live in the project. When ran from an executable, you have to preload your classes to fill the lookup table (there's a VI for that too). Edited May 26, 2014 by CharlesB Quote Link to comment
Stobber Posted May 26, 2014 Author Report Share Posted May 26, 2014 It's in <vi.lib>/NI/Class Retrieval/ Not on my installation. That's the folder NI uses for their VIPM packages...maybe you installed a package that's not on the public server? Quote Link to comment
CharlesB Posted May 26, 2014 Report Share Posted May 26, 2014 (edited) You have to install it from VIPM (LV Tools Network), it's called "Class Retrieval". And it's indeed a NI package from Allen. Edited May 26, 2014 by CharlesB Quote Link to comment
Aristos Queue Posted May 27, 2014 Report Share Posted May 27, 2014 (edited) CharlesB: You'll find that the class retrieval has a really nasty performance curve. There really isn't a good solution until 2013... I tried hard to find one, but hit too many performance issues with every other approach, and finally cut a new interface into LV. (To be clear... it does work... and if you don't have a tight loop, it works fine. It's the performance that was the issue.) Edited May 27, 2014 by Aristos Queue Quote Link to comment
CharlesB Posted May 28, 2014 Report Share Posted May 28, 2014 Thanks for clarifying; performance isn't an issue for me, as it'll be used for configuration files loading, which happens at software start, so even if I get 1 or 2s hit it's OK. Quote Link to comment
Mike Le Posted May 31, 2014 Report Share Posted May 31, 2014 (edited) To specify the location of the .lvclass file inside the EXE, add it to the "Always Included" list in the build spec, then create a "Destination" for it with the full path. For XYZ.lvclass, an example Destination Path would be C:buildMyApp.exeXYZ. When you want to load an object of XYZ at run time, you provide the path C:buildMyApp.exeXYZXYZ.lvclass I'm running into a really weird issue with this workaround. I created many destinations like this and it seems to work as desired: the files get built into the exe. However, now the Installer fails to build correctly. The Installer seems to think that "MyApp.exe" is an actual system folder. It looks for my lvclasses in this nonexistent system folder and returns an error when it can't find them. Has anyone run into this before? Is there something wrong with the way I defined my destinations? EDIT: I know that the "Yen" symbol is showing up instead of backslash; that's some weird artifact of my virtual machine that I haven't sorted out. But rest assured the same issue manifests itself on normal desktops that display the backslash as normal. Edited May 31, 2014 by Mike Le 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.