Jump to content

LabVIEW Built DLLs and Library Versions


Recommended Posts

I've never built a DLL using LabVIEW before, but am starting to think this may be the way to go for a component I'm working on. However I have one concern where my google-fu is failing me and thought I'd lob this one over the fence since at least of the lava gurus here likely knows the answer.

 

Consider this situation:

 

My DLL is built and includes SharedLibrary.lvlib (version 1).

My EXE is built and includes SharedLibrary.lvlib (version 2).

 

That is both the DLL and EXE reference the same library, all be it incompatible versions. Each fully includes all the dependencies they need to run on their own. With respect to each library version, the namespaces are identical-- that is we don't have SharedLibraryVersion1.lvlib and SharedLibraryVersion2.lvlib, but two different versions of SharedLibrary.lvlib.

 

Now let's say my EXE needs to dynamically load my DLL: Do I have a problem? Am I going to run into any weird namespace collision issues? I would hope everything should be locked properly behind their respective boundaries, but...

 

If this is a problem it's no big deal, I could always change the DLL into another executable, but I'd rather not as it makes a bit of a mess of passing data in and out.

  • Like 1
Link to comment
I've never built a DLL using LabVIEW before, but am starting to think this may be the way to go for a component I'm working on. However I have one concern where my google-fu is failing me and thought I'd lob this one over the fence since at least of the lava gurus here likely knows the answer.

 

Consider this situation:

 

My DLL is built and includes SharedLibrary.lvlib (version 1).

My EXE is built and includes SharedLibrary.lvlib (version 2).

 

That is both the DLL and EXE reference the same library, all be it incompatible versions. Each fully includes all the dependencies they need to run on their own. With respect to each library version, the namespaces are identical-- that is we don't have SharedLibraryVersion1.lvlib and SharedLibraryVersion2.lvlib, but two different versions of SharedLibrary.lvlib.

 

Now let's say my EXE needs to dynamically load my DLL: Do I have a problem? Am I going to run into any weird namespace collision issues? I would hope everything should be locked properly behind their respective boundaries, but...

 

If this is a problem it's no big deal, I could always change the DLL into another executable, but I'd rather not as it makes a bit of a mess of passing data in and out.

 

There is no easy answer to this. As with most things the right answer is: it depends!

 

If your LabVIEW DLL was created with a different version than the LabVIEW version you are running your lvlib in, you are safe. The DLL will be executed in the context of the runtime version of LabVIEW that corresponds with the LabVIEW version used to create the DLL. Your LabVIEW lib is executing directly in the calling LabVIEW system, so they are as isolized from each other as you can get on the same machine instance.

 

However if you load the DLL into the same LabVIEW development system version as was used to create it, things get more interesting. In that case LabVIEW loads the VIs inside the DLL into the same LabVIEW system to save some performance. Loading the DLL into a different LabVIEW runtime requires marshaling of all function parameters across process boundaries, since the runtime system is a different process than your LabVIEW system, which is quite costly. Short circuiting this saves a lot of overhead. But if the VIs in the DLL are not in the same version as the current LabVIEW version, this can not be done as the DLL VIs are normally stored without diagram and can therefore not be recompiled for the current LabVIEW platform.

 

So in this case things get a bit more complicated. I haven't tested so far if VIs inside DLLs would get loaded into a special application context in that case. It would be the best way to guarantee as much of similar behavior as if the DLL had to be loaded into a separate runtime. But it may also involve special difficulties that I'm not aware of.

  • Like 2
Link to comment
I've never built a DLL using LabVIEW before, but am starting to think this may be the way to go for a component I'm working on. However I have one concern where my google-fu is failing me and thought I'd lob this one over the fence since at least of the lava gurus here likely knows the answer.

 

Consider this situation:

 

My DLL is built and includes SharedLibrary.lvlib (version 1).

My EXE is built and includes SharedLibrary.lvlib (version 2).

 

That is both the DLL and EXE reference the same library, all be it incompatible versions. Each fully includes all the dependencies they need to run on their own. With respect to each library version, the namespaces are identical-- that is we don't have SharedLibraryVersion1.lvlib and SharedLibraryVersion2.lvlib, but two different versions of SharedLibrary.lvlib.

 

Now let's say my EXE needs to dynamically load my DLL: Do I have a problem? Am I going to run into any weird namespace collision issues? I would hope everything should be locked properly behind their respective boundaries, but...

 

If this is a problem it's no big deal, I could always change the DLL into another executable, but I'd rather not as it makes a bit of a mess of passing data in and out.

Well.

 

A DLL is a self contained list of compiled executable functions (they are not equivalent to programs). If you call a function using the CLFN I don't think it has anything to do with any libraries you have placed on the block diagram (scope-wise). As long as the function exists in the DLL and the there is only one DLL with that name, that is all that is required (parameter lists of course need to be considered). Unless you are dynamically loading an external lvlib from the DLL (which is a bit silly), I don't really understand the question.

 

DLLs are meant to make programs modular just as lvlibs are. It tends to be one or the other with lvlibs being native to labview. If you have compiled a lvlib into a DLL, then your exe will use whatever version of the lvlib you compiled the DLL with (your program only knows of the function name and parameters to pass). Replace the V1 DLL with the V2 DLL and your program will not know much is different unless the parameter lists have changed for the function calls. That's the whole point of them-so you can update/modify parts of the code without affecting/recompiling everything else.

 

That said...... There are a couple of caveats that are peculiar to LabVIEW DLLs specifically. Rolf has outlined a bit of it in that LabVIEW DLLs have a huge dependency on the run-time and it's not easy to know what those dependencies are. So you can find yourself a while down the road backed into a corner and installing every version of labview run-time known to man to keep the various bits of your "modular" code that you have developed over several LV versions  working and wondering why, this time around, it runs like a slug.

 

You also lose your cross-platform capabilities too! (Cannot create .so or dylibs/frameworks with LabVIEW)

 

My advice is don't use Labview DLLs unless it's for use in another programming language and your options to provide an interface for them are limited. Other languages executables don't have the same dependencies as LabVIEW executables so are less likely to run into version problems between the DLL and the program itself.

  • Like 1
Link to comment
Well.

 

A DLL is a self contained list of compiled executable functions (they are not equivalent to programs). If you call a function using the CLFN I don't think it has anything to do with any libraries you have placed on the block diagram (scope-wise). As long as the function exists in the DLL and the there is only one DLL with that name, that is all that is required (parameter lists of course need to be considered). Unless you are dynamically loading an external lvlib from the DLL (which is a bit silly), I don't really understand the question.

 

DLLs are meant to make programs modular just as lvlibs are. It tends to be one or the other with lvlibs being native to labview. If you have compiled a lvlib into a DLL, then your exe will use whatever version of the lvlib you compiled the DLL with (your program only knows of the function name and parameters to pass). Replace the V1 DLL with the V2 DLL and your program will not know much is different unless the parameter lists have changed for the function calls. That's the whole point of them-so you can update/modify parts of the code without affecting/recompiling everything else.

 

That said...... There are a couple of caveats that are peculiar to LabVIEW DLLs specifically. Rolf has outlined a bit of it in that LabVIEW DLLs have a huge dependency on the run-time and it's not easy to know what those dependencies are. So you can find yourself a while down the road backed into a corner and installing every version of labview run-time known to man to keep the various bits of your "modular" code that you have developed over several LV versions  working and wondering why, this time around, it runs like a slug.

 

You also lose your cross-platform capabilities too! (Cannot create .so or dylibs/frameworks with LabVIEW)

 

My advice is don't use Labview DLLs unless it's for use in another programming language and your options to provide an interface for them are limited. Other languages executables don't have the same dependencies as LabVIEW executables so are less likely to run into version problems between the DLL and the program itself.

 

Shaun, in theory you are right. In practice is a LabVIEW DLL a C wrapper for each function that invokes the according pre-compiled VI inside the DLL. As such there needs to be some runtime support to load and executed these VIs. This is usually happening inside the according LabVIEW runtime which is launched from the wrapper. Some kind of Münchhausen trick really. However at least in earlier versions of LabVIEW if the platform and LabVIEW version of the compiled DLL was the same as the calling process, then the wrapper invoked the VIs inside the DLL directly in the context of the calling LabVIEW process.

Link to comment
Shaun, in theory you are right. In practice is a LabVIEW DLL a C wrapper for each function that invokes the according pre-compiled VI inside the DLL. As such there needs to be some runtime support to load and executed these VIs. This is usually happening inside the according LabVIEW runtime which is launched from the wrapper. Some kind of Münchhausen trick really. However at least in earlier versions of LabVIEW if the platform and LabVIEW version of the compiled DLL was the same as the calling process, then the wrapper invoked the VIs inside the DLL directly in the context of the calling LabVIEW process.

 

Perhaps I didn't make it clear. I was not suggesting that other languages don't need the run-time. Just that they only need the 1 run-time as opposed to, say, a labview 2011 exe with a 2009 dll which needs two, I believe.

Link to comment

Valuable info, thanks.

 

This is coming up because of supporting legacy versions serialization code. A while ago we made a switch from a proprietary binary storage format to a database back end (wonder what that could be, Shaun?). I want to lock down our legacy code which manages the binary versions and the binary to database conversion. This will be a component build from fixed revisions from our source code repository. Since I'm literally pulling out code from our last iteration and building it to a stand-alone component, I can re-use our existing test cases to validate the code, and deem it working. We are now free to make changes to our database interface (how the actual VI calls are made, not the schema), because we don't need to worry about breaking the existing conversion code-- it is locked away in an independent component.

 

I had not thought about the different run-time engines, but that is a very good point. I definitely don't want to have to distribute multiple LabVIEW, MSVC, and SQLite redists, so I suppose this component would have to be recompiled in whatever flavor of run-times I'm using at the time. However the recompile would still be from legacy versions of our source code, and could be tested with legacy unit tests. Our core development would still be free from having to support the old API we were using in this legacy code.

 

To that effect I threw together a quick proof of principle. I made a DLL with an exported function which makes a call to a VI qualified as Shared.lvlib:Version.vi and returns the number. I made an EXE which loads the DLL and shows the return value, all the while making a call to a similarly named VI which it includes. The EXE and DLL do indeed each use their own version of Shared.lvlib:Version.vi and return different values. Success I think?

 

DLL Test.zip (LV2012SP1, built DLL and EXE included)

Link to comment
definitely don't want to have to distribute multiple LabVIEW, MSVC, and SQLite redists, so I suppose this component would have to be recompiled in whatever flavor of run-times I'm using at the time. However the recompile would still be from legacy versions of our source code, and could be tested with legacy unit tests. Our core development would still be free from having to support the old API we were using in this legacy code.

A common way of solving this with the minimum effort is to create a conversion tool. It only needs to be created once, then you can forget about it and eventually you will no longer need it. Some even offer the feature as a menu option in the main application which just invokes the converter. If it's easy to spit out your custom format as a delimited text file or a number of files, you can easily import them with the API File tools (2 steps rather than one, but may be a lot easier).

Link to comment

Indeed, that's exactly what we are doing by breaking out this code to a stand-alone component, be it a DLL or EXE. It will be self-contained with it's own versions of whatever it needs.

 

The DLL is nice in that it allows relatively easy passing of parameters between the new and legacy code. If we go an EXE route, we need to create some sort of wrapper to pass things out since we don't have access to stdout/errout or the exit code in LabVIEW (passing things in is easy via the command line).

Link to comment
Indeed, that's exactly what we are doing by breaking out this code to a stand-alone component, be it a DLL or EXE. It will be self-contained with it's own versions of whatever it needs.

 

The DLL is nice in that it allows relatively easy passing of parameters between the new and legacy code. If we go an EXE route, we need to create some sort of wrapper to pass things out since we don't have access to stdout/errout or the exit code in LabVIEW (passing things in is easy via the command line).

 

DLLs cannot be run standalone. You always need a host application.

 

Why do you need a parameter interface between "new and legacy" code? What I was suggesting is you just pass in a filename to process, a filename for output (cmd line parms) and hey presto you get the db that your real application can use. You can put it on your website for people to download if they need it (perhaps bundle it with the main app to begin with) and once their files have been converted, they will no longer require it at all. It never needs clutter your application code-base, rather,  a separate project as a bridge to deprecation of the old file format..

Link to comment

Well, host application is really just semantics. A LabVIEW exe requires the LabVIEW RTE to interpret what's inside. You can make similar arguments for "native" applications in windows, whether or not it's an actual runtime or just dependencies doesn't really matter in the end. Ever try to run visual studio compiled C++ executables on a fresh install of Windows that predates the compiler? Good luck with that unless you have an MSVS redistributable around. In the end it's just a hierarchy of dependencies, the only real difference is the exe has all the required info for the operating system to recognize it as something it can "execute".

 

Regardless, I want to get error feedback from this tool. When my application loads this code and executes it, I want to know if it was successful. I've already added a command line interpreter that recognizes the request to serialize an exit state to a file. This is really all I need. It's more straightforward though to be able to just park on the DLL call than to have to decide on a temp location, and wait for that temp file to be populated with information before continuing.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.