Search the Community
Showing results for tags 'dynamic dispatch'.
-
I've run across an interesting difference in how LabVIEW 2016 works with dynamic dispatch VIs compared with 2015. If you put the class wire on a shift register of a loop and then have an event structure inside it and in one of the event cases instead of wiring the shift register through, you wire whatever value was originally put into the shift register through (you might do this if you're making a dialog to configure the class and want to let the user cancel it without affecting any changes) it breaks your VI - it doesn't consider this to be a "good enough" way of wiring your dynamic dispatch input to the output. However, if you have this same code in LabVIEW 2015, it works perfectly fine. See attached code for an example - if you open it in 2016 the run error is broken, in 2015 it is not. It is the exact same code. Does anyone know if whether this is a bug or just new, intended behavior? --Hope Bug Test.zip
-
I am trying to wrap my head around something i've been dealing with lately: I want to implement a "Messenger" Class for facilitating a switch of communication interfaces in my programs. Basically my current thought process is that I have: - A parent class called "Messenger" with the methods: initialise(?), connect(), [U8] recieveData(), sendData([U8]), disconnect(), that I can use in my code. - A child class "TCP Messenger", which overrides the methods: initialise(IP, Port, Timeout, DVR, ConnectionType), connect(), [U8] recieveData(), sendData([U8]), disconnect(). - A child class "Serial Messenger", which also overrides the methods: initialise(Port Number, Timeout, DVR, ConnectionType), connect(), [U8] recieveData(), sendData([U8]), disconnect(). - A child class "Profibus Messenger", which again overrides the methods: initialise(FPGA ref, SlaveAddress, ConnectionType), connect(), [U8] recieveData(), sendData([U8]), disconnect(). ... I would like to change the communication type by simply loading a different class and letting dynamic dispatch do the rest. All of the methods have similar interfaces, except the initialise method, as every type of connection necessitates different types of parameters. Everything else is basically getting byte Arrays and setting Byte arrays. How would one go about solving this? Do I just create an Initialise method with every possible parameter and only use what I need in the specific implementation? Robert
-
Hello All, Long time reader, first time poster. I have learned a lot from lavag, and really appreciate what you all do here. I am building an LVOOP architecture that sort of straddles the line between AMC and AF. One of the most frustrating things I have run across (as with most AF type architectures) is debugging shared clones. I've run into some behavior that I did not expect and wanted to see if anyone knew what was going on. First some definitions: Behavior A: Opening a Shared Clone Reentrant subVI from the block diagram of a running VI opens the original, "uncloned" VI, reserved for execution. Behavior B: Opening a Shared Clone Reentrant subVI from the block diagram of a running VI opens the active, running clone VI, which is capable of being debugged. I once thought that behavior A was how LabVIEW worked, however in developing this framework, I have found that some subVIs show behavior B. Behavior A and B seem to correlate to dynamic and static dispatch methods respectively, but I can't make sense of why. If I create a simple example without OOP (see attached), I get behavior A. Has anyone ever seen this behavior, and if so, am I missing something really obvious? Secondly, does anyone have any tricks or best practices for getting into active clones to debug? My only idea at this point is to include some sort of notifier/queue/etc to active a Front Panel Open Method. Thanks in advance! Drew T. CLA, CTA
- 8 replies
-
- debug
- reentrancy
-
(and 3 more)
Tagged with:
-
Hi, Here comes a rather basic question but which I'm always struggling with since you can often argue both ways. Hopefully some of you have a few nuggets to share here... 1) A parent class should have no knowledge of any child class' concrete type, i.e. only data and methods that is inherently common to all decendents of that parent should be defined by it. 2) For dynamic dispatching to work the parent class must define virtual methods for dynamic dispatchees to work from. Those two rules often contradict each other. Methods vetted against 1) will often eliminate the possibility of 2). A specific example: Currently at GPower we're working on a set of classes that enables us to do a lot of stuff on all the different LabVIEW files. So, we have a parent file.lvclass and then a collection of specific children that inherits from "file", for instance vi.lvclass, lvproj.lvclass, ctl.lvclass, facadevi.lvclass etc. A) Generic stuff that has to do with any file obviously goes into file.lvclass data (together with data member access methods for each). For instance IsWriteprotected?, FileSize, FilePath and such. A FileRefnum should probably go into each child class to enable us to have it most specific. B) Then there are data elements that definetely has to do with each concrete file type and thus should be in each child class' private data, such as AllowsDebugging?, IsFPStyleOK?, Icon etc. - as those are only valid for a subset of file types. C) Now it gets a bit more murky; If we define data elements in file that each child can use to flag if it has this or that feature (like HasIcon? or SupportsProtection?), then you can ask each and every file type if it support that, before calling a method to work on that. For the subset of file types that supports a given feature (those that has an icon for instance) it'd be great to have dynamic dispatching though. But for that to work file.lvclass would have to implement virtual methods like GetIcon() and SetIcon() (where the latter maybe recalculates the IsIconStyleOK? data field for instance). But implementing these (numerous it turns out) virtual methods in the parent class, suddenly riddles the parent class with specific knowledge or nomenclature that is very specific to different subsets of descendent file types. I always vet the parent against each piece of information I'd like to put in there by asking myself something like this: Does my generic file know anything about disk write protection? Yes, all files deal with that, so it can safely go into file.lvclass. Does my generic file know anything about block diagrams? No, only a handful LabVIEW file types knows about block diagrams, so I can't put it into file.lvclass. But the latter forces me to case out the different file types in my code, so I can call the different specific methods to work on block diagrams for those file type objects that supports this. Hence, if I want to be able to just wire any file type object into a "block diagram worker" method I need dynamic dispatching, and that only works if my parent has a virtual method for me to override with meaningful code in a few child classes... How do you go about selecting this balance, on one hand abstracting the parent from the concrete types, and on the other hand implementing the necessary dynamic dispatch virtual methods in the parent? Regards, Steen I must add that I'm currently leaning towards the more pure approach of not mixing abstract and concrete. Thus I tend to omit dynamic dispatching except for the very generic cases. I only allow the "do I support this feature" flags into the parent data, and then I implement static dispatch methods for each concrete type - even though these static dispatch methods then will often be quite similar, but that is solved with traditional LabVIEW modularization and code reuse (like subVIs, typedefs and such). It works well, but I feel I don't get the full benefit of dynamic dispatching. But that is what I'd do in C++... /Steen