LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Problems passing ActiveX dll refnum from VI to VI via local, global variables

I have  a Visual Basic ActiveX DLL  with several functions including Init and RWReg.  Init creates a new class instance and does some initialization.  RWReg calls functions from the class to read/write some hardware registers.  I have also created Init.vi and RWReg.vi.  These are wrappers around the Init and RWReg ActiveX method calls (see attached init.pdf for example).  Here's my problem:

When I call Init.vi and RWReg.vi in succession and wire the refnum output of init.vi to the refnum input of RWReg.vi directly everything works fine and I can read/write registers.  On the other hand, when I pass the refnum from Init.vi to RWReg.vi via a local variable (see attached refnum_problem.pdf), I get the following error:

Code1:  Incorrect function. in cvg_RWReg.vi

I've tried passing the refnum using global variables and functional global variables with the same result.  It appears to me that unless the refnums are hardwired between separate VI calls, Labview clears the DLL from memory.  Is there a way to get around this?  I would like to be able to call Init.vi to initialize the class, then to be able to call RWReg.vi separately to read/write registers once the Init.vi has closed.  Can I accomplish this without hardwiring the refnums?  Would I have the same issue (DLL cleared from application memory after VI closes) if I had a standard Windows DLL instead of an ActiveX DLL?

Thanks,

Dan
Download All
0 Kudos
Message 1 of 13
(3,628 Views)
You have classic race condition. The local/global variable is being read before a value is written to it. Remember, LabVIEW is a dataflow language, not a procedural language like C. Code does not necessarily execute left to right.
0 Kudos
Message 2 of 13
(3,623 Views)
Forgot about the second part of your question: If your Init and RWReg are within the same VI there is no need to use a local variable like you're doing. In your final program are these VIs going to be in separate VIs? If so, you need to keep in mind that the refnum will only be valid while the top-level VI is still running.
0 Kudos
Message 3 of 13
(3,621 Views)
That's precisely right, I was hoping to use separate vi's to call different dll functions in succession without a top-level VI running.  Isn't one of the benefits of shared libraries/DLLs that the code can be accessed (and data shared) in the same memory space by different concurrent applications  (I'm new to dlls, so correct me if I am wrong)?  Shouldn't I be able to pass a pointer to that memory space from one VI to the next without that memory being de-allocated?  Regarding the potential race condition, I've also tried passing the refnum by reading/writing a global variable inside the respective VI's (in which case there should be no race conditions since the vi calls are wired and called in succession) with the same result.
0 Kudos
Message 4 of 13
(3,613 Views)
Hi snowdust,

Please refer to the KnowledgeBase article titled Reference Local Variable Does Not Return the Correct Value.  Basically, the (likely) problem here is that the local variable is being read before a valid reference is placed in the "refnum" indicator. 

Did adding a flat sequence structure fix the problem?
0 Kudos
Message 5 of 13
(3,589 Views)

Hi Snowdust/ Peter K.

I have been experiencing similar problems using ActiveX to access a COM Object for communication with an external hardware module. I created a Cluster in the top Level Vi to store the reference and then generated the refnum in a SubVi using the Automation Open function and before exiting the SubVi stored the refnum in the Top Level Cluster (via Local Variable) prior to exiting the SubVi. Although I had not closed the reference (Close Reference function) the refnum seemed to be lost. 

Question to Peter K. Is there a way around this problem where I don't have to hardwire the Refnum as I the design is highly architectural and hardwiring would be very messy (and cumbersome)? Would creating (and storing in the cluster) the refnum in the Top Level Vi  make this available for use in all SubVi's within the Hierarchy of the Top level Vi?

Regards

Ian Melville

   

0 Kudos
Message 6 of 13
(3,580 Views)
Peter,

I just gave a bad example initially with the potential of a race condition.  In fact, the same problem occurs if I have the local variable read/write operations inside different frames of a sequence, if I have a global variable written/read by different vi's, etc.   In short, it occurs whenever I try to pass the automation refnum in any other way than wiring it directly from vi to vi.  This seems to be corroborated by Ian's experience (and his question is exactly the one that I have). 

Regards,

Dan
0 Kudos
Message 7 of 13
(3,562 Views)

I'm not convinced these are both the same issue.

Ian's issue may be realted to LV clean-up routine If the VI that is opening the resource goes idle, all of its allocated resource are marked as invalid. You have to make sur ethe enitity that opens a resource is active as long as the resource will be used. That issue can be handled using an Action Engine.

Some screen shots will help up chase down these issues. Please post png or jpg since not all of as viewers for pdf's.

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 8 of 13
(3,555 Views)
Hi all,

I've discovered a related issue that's even more troubling.  I've created several VI's as wrappers for some ActiveX DLL routines.  It appears that even if I pass refnums from VI to VI by wiring them, if I recompile the DLL I have to manually re-link the refnums in every single VI and subVI that calls the DLL (even if the calls themselves haven't changed).  Otherwise, I get broken wires between VI's because the output refnum of one VI is linked to a different version of the DLL than the input of the next VI.  This is extremely frustrating, especially when the DLL is frequently recompiled during debugging.  Is there any solution to this?  If I am not changing any of the function interfaces in the DLL, can I fool Labview/Windows/VisualBasic into believing that the DLL version hasn't changed?

Finally, since there appear to be these issues with ActiveX DLL's and Labview, will my life be any easier if I recompile the DLL as a regular Windows DLL?  I think I've found a way to coax Visual Basic into doing that (although this too is a significant investment of time).

Regards,

Dan
0 Kudos
Message 9 of 13
(3,540 Views)

FIrst I would again urge you look into the Action Engine. Set it up such that is has an Init method, methods for each call,.... and also a close method. Keep the ref in a shift register inside the AE (works like a static local) and make all of your calls to the dll using the AE. This way you just have to update the AE with you re-compile.

Another thing that could help you is to use Type-Definitions for you ref num. I wrote about those in another Nugget that can be found here. They let you make the change once and the change is realized everywhere the type-def is used.

THe recompiling makes sense and is correct. LabVIEW enforces all of the details associated with function call protypes etc. so as a developer you just wire and run. Burried inside you refnum is the info for the calling standard. By forcing you to redifine the refnums, LV is helping you ensure you dod not do an illegal function call that could result in very bad things happening. Smiley Mad

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 10 of 13
(3,526 Views)