LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Lvoop based DLLs

I recently completed a LVOOP-based spectrometer driver for a LV application that has been working very well for my company.  So well, in fact, that I've been asked to turn the driver into a DLL so a C++ based application can use it.  My problem is that I know nothing about writing DLLs in LabVIEW.  My only experience with DLL writing was in C - about 12 years ago.  I know I'll have to find a way to flatten the objects to datatypes I can pass around, but I'm very sketchy on details.  I want to read up on this topic and take a few shots myself before I ask any specific questions... I went through the knowledgebase and the forum, but my search didn't find anything particularly useful.  Can anyone here point me at some resources to learn about writing DLLs in LV8.6 (or even 2009) - particularly when LVOOP is involved?   

 

Thanks,

Jason

 

 

0 Kudos
Message 1 of 13
(2,117 Views)

Hi Jason,

 

I did a bit of digging for you and this it what I came up with.  

 

It is possible to convert a LVOOP program to a DLL, but no objects are passed as inputs into the vis.  Maybe the following expert will explain it better:

 

(This is an expert from the DeveloperZone LabVIEW Object-Oriented Programming: The Decisions Behind the Design)

 

Why does LabVIEW forbid LabVIEW classes in the interface of LV-built DLLs (shared libraries)?  Why can't I pass LabVIEW objects to a Call Library Node?
When you use Application Builder to build a DLL (or shared library on other platforms), LabVIEW will not allow any VI to be exported from that DLL if the connector pane of the VI uses any LabVIEW classes. The interface between LabVIEW and external code must be in plain data types.

If you look back at the in-memory layout of a class instance, you’ll see that there’s a lot of very LabVIEW-specific pointers and allocations. No other EXE or DLL will have any ability to use that data structure or get access to the pieces of the class needed to support dynamic dispatching or to enforce class scoping. Similarly, the C++ implementation of classes varies from compiler to compiler. Most C++ users will advise against putting C++ classes in the interface of DLLs because of this variance. The nature of OO is such that the implementation structure that is best for one compiler is not good for another, and so they rarely can interact with each other.

 

 

As for the process of creating a DLL, check out the LV Help.  Index >> Shared Libraries >>building (how-to).

 

I hope this helps!

 

Kristen H.

0 Kudos
Message 2 of 13
(2,093 Views)

Hi,

 

I knew that I couldn't pass objects into/out of a DLL, but what I'm wondering is - can I pass them BETWEEN the functions inside the DLL?  If I call a VI in the DLL, can that VI pass an object to one of it's subVIs in the same DLL? 

 

Thanks,

Jason

0 Kudos
Message 3 of 13
(2,076 Views)

Jason P wrote:

Hi,

 

I knew that I couldn't pass objects into/out of a DLL, but what I'm wondering is - can I pass them BETWEEN the functions inside the DLL?  If I call a VI in the DLL, can that VI pass an object to one of it's subVIs in the same DLL? 

 

Thanks,

Jason


Yes! Use of classes inside the DLL should be no problem. The issue is at the DLL interface.

 

I find the exact explanation in Kristen's answer a little vague but otherwise good. Yes C++ object interfaces are generally not binary compatible between different C compilers and often even between different major versions of the same compilers. 

 

And this is the same with LabVIEW object interfaces that have no meaning in a different LabVIEW runtime kernel version. All odds are up if you would try to call such a DLL function from a non-LabVIEW environment. Such a program has absolutely no glue how to deal with the data structures that are hidden behind the object class refnum. And NI for various reasons is not going to document that interface, the most prominent being that once it's documented, it hardly can be modified.

Rolf Kalbermatter
Averna BV
Message 4 of 13
(2,068 Views)

OK - I understand I have to be very careful about using standard datatypes when interfacing with my DLL.  This should be no problem for my app... all I really need to do from the app is send the DLL some integers and receive some arrays of floats back.

 

The second question I have is about data persistance.  If I can pass objects between members of the DLL, can I use an action engine (uninitialized shift register) in the DLL to store those objects between calls?  In my driver, I initialize a spectrometer object and use it to hold all the data specific to that spectrometer.  This data is used in all subsequent function calls.  With that in mind, assume I have to make two function calls later - setGain and requestSpectra.  Both of those will need access to the initialized object - can they get it from the AE?

 

Sorry to be asking so many questions here, but after a thorough web search I haven't been able to find much at all about DLL creation in LV beyond very simple toy examples.

 

Thanks,

Jason

0 Kudos
Message 5 of 13
(2,060 Views)

Hi Jason,

 

I did a quick test concerning data persistance with DLL calls.  My initial thoughts were confirmed.  Because the DLL is loaded into memory and not disposed of until all the references to it are cleared (either by calling Close Reference VI or closing the VI calling the DLL), the value will be maintained in the unitialized shift register. 

 

This is was is inside my VI that I created into a DLL: 

 Caller.png

This is the calling VI:

Caller.png

"Return type 2" returned a 7, "return type" returned a zero.  Therefore, the value was maintained in the shift register throughout both DLL calls.  

 

Have you tried creating a small test program?  I hope this helps!

 

Kristen H.

Download All
0 Kudos
Message 6 of 13
(2,036 Views)

Hi Kristen,

 

Thanks for staying with this - I haven't had the chance to create a test program yet.  I found a glitch in my driver that I had to take care of first.   

 

I'm assuming that as long as the C++ program remains active, the DLL will remain in memory and the AE will continue to hold data... I'll let you know if I find something different.  But given the answers from both you and RolfK, I think I have the pieces I need to pull it off. 

 

Thanks,

Jason

0 Kudos
Message 7 of 13
(2,026 Views)

Another C++ friendly option would be to use Data References to hold your class objects. This is a new feature in LabVIEW 2009. You can't export a function for a DLL from a VI that has a class object on the connector pane, but you can export a function with a Data Reference to a class object on the connector pane.

 

On the C++ side, for 32-bit Windows, this Data Reference can be treated like an opaque I32.

 

If you don't have LabVIEW 2009, you can do the same thing with a single-element queue.

 

Both options require writing wrapper VIs around your class API that create and use these Data References. Attached is an example. Build the DLL and relink the Call Library Function Nodes in the Example VI to see it. The example uses LabVIEW 2009 because of the data references.

 

Jarrod S.
National Instruments
0 Kudos
Message 8 of 13
(2,010 Views)

Jarrod,

 

I do have LV 2009, and that approach sounds like something I may want to use in a future project that's been running around in my head.  But for this app, I just need the C++ app to set and get a few simple data types.  The original project was a LabVIEW driver for a single spectrometer.  It was to be used with a LV app, so no problem.  That grew into a driver that could handle any of 3 types of USB spectrometers, with a 4th unknown type to be added sometime in the future.  So I turned the original driver into an NI-VISA/LVOOP based driver, using dynamic dispatch to handle each spectrometer type.  And after seeing how well it worked with the LV app, my co-workers asked me to turn it into a DLL for use in a C++ app.  Sigh - gotta love that scope creep... Smiley Happy

 

The need to use classes in the DLL comes more out of a desire to maintain the driver in its current state than anything else.  But I have to say, it's nice to spend a bit more time with LVOOP.  And having a legitimate excuse to learn how to write a DLL in LV on company time - that's just the icing on the cake... 

 

Jason

0 Kudos
Message 9 of 13
(1,998 Views)

Sounds good!

 

And as a vote of confidence, I've used Action Engines in LV-built DLLs before and they perform as expected.

Jarrod S.
National Instruments
0 Kudos
Message 10 of 13
(1,996 Views)