12-11-2020 07:50 AM
Dear All,
I have created a simple DLL in VC++ with one function that adds two numbers. Lets call this "LibraryA.dll".
I have created a second simple DLL in VC++ with one function. This function uses "LoadLibrary" to load LibraryA.dll and returns the result of trying to load LibraryA.dll (success or failure). Lets call this "LibraryB.dll" If loading LibraryA.dll was successful, the function waits 1 second and then uses "FreeLibaray" to unload LibraryA.dll.
In all cases I have added extern "C" to the function exports so they can be called from LabView.
Next, I have a simple Windows console application (made in VC++) that loads LibraryB.dll and then calls the function inside LibraryB.dll to load LibraryA.dll. The result of trying to load LibraryA.dll is printed to the cmd window. In this case, LibraryB.dll successfully loads LibraryA.dll as expected.
Finally, I've made a LabView VI that uses a Call Library Function Node to call the function in LibraryB.dll which should load LibraryA.dll. This fails and LibraryA.dll is not loaded.
However, if I add a second Call Library Function Node that has been set to call the function in LibraryA.dll and place this inside a "Disable Diagram" then LibraryB.dll is able to load LibraryA.dll.
If I have a solution why am I asking this question? I have a DLL from a company to control their hardware. Their DLL loads a number of other DLLs. Everything works when I use their DLL in a VC++ console application. However, when I try to use their DLL in a LabView VI things fall apart. I suspect this is all related.
Any advice on how to have LabView load a DLL that loads other DLLs?
Thanks!
12-11-2020 08:47 AM
Windows DLL search paths!
In Visual C you end up with this:
<your app dir>
<your app>.exe
LibraryA.dll
LibraryB.dll
In LabVIEW project you end up with this:
C:\Program Files (x86)\National Instruments\LabVIEW 2020
LabVIEW.exe
<Data>\<your Project>
MyProject.lvproj
My Function.vi
LibraryA.dll
LibraryB.dll
You tell the VI in MyFunction.vi where LibraryB.dll is located and LabVIEW happily tells Windows please load that. Then you call the function in that DLL which tells Windows "please load LibraryA.dll"!
But from where? Windows only searches specific directories for DLLs, and the directory in which a DLL is located that calls LoadLibrary() is NOT part of those locations.
The search order goes basically like this:
1) already loaded in memory, do nothing and use that
2) in the directory where the current processes exe file resides
3) in the Windows\System32 (SysWOW64 for 32-bit Windows application under Windows 64)
4) in the Windows directory
5) in the current directory, a process global variable that is initialized to location 2) above on startup but can be reconfigured by an executable by calling Windows API calls, but what is worse, it is changed everytime the file dialog is dismissed other than by cancel to whatever directory it was pointing at
6) last but not least all directories listed in the PATH environment variable.
For your Visual C example it succeeds since rule 2) is successful. For LabVIEW (and other more complex applications it can not succeed).
Copying your LibraryA.dll into the folder where LabVIEW is located would solve that, but that is BAAAAD. Not much better is copying your DLL into the Windows or System32 directory.
you could be trying to be very smart and implement an intelligent path building in your LibraryB.dll that determines its own path, then removes the LibraryB.dll name from that path and replaces it with LibraryA.dll and then tries to load that. After that you could try other paths that you decide upon and only when all those fail, try to simply load "LibraryA.dll" and let Windows search.