LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

MATLAB DLL C Wrapper initialize and terminate, part 2

Solved!
Go to solution

I'm referencing this very old thread since it forms a part of a backstory, but doesn't resolve my issue directly and would like to find the root of the issue:

 

https://forums.ni.com/t5/LabVIEW/Matlab-Dll-Initialize-and-Terminate/m-p/285894

 

I have a MATLAB C DLL compiled using MATLAB 2017A (fully 64 bit), and the respective version of the Compiler SDK. I used Visual Studio 2017 Community (again, fully 64 bit...bitness is not the issue) to create a wrapper and console application to independently verify the DLL. The console application works fine, both as a single DLL function, and by calling separate init, function, term functions.

 

When I import the DLL into Labview 2016 64bit, the import goes fine and the first run of the DLL file works just fine. However, Labview reports an  exception from the DLL when the VI is run a second time or more. In my investigation, it looks like the MATLAB terminate functions fail the first time, and consequently the initialization of the next VI run fails, and crashes Labview.

 

I sincerely do not believe it is a DLL issue, since the console application calling the same DLL runs perfectly.

 

Any thoughts or fixes that aren't covered in the original thread referenced above?

0 Kudos
Message 1 of 15
(6,187 Views)

I've looked at all the documentation on the Mathworks site, and whatever I could find googling for NI.com as well. Mathworks technical support also wasn't able to help, so that is why I'm here, because I think it is a Labview issue. A simple C application can use the DLL just fine.

0 Kudos
Message 3 of 15
(6,103 Views)

@raceybe wrote:

I've looked at all the documentation on the Mathworks site, and whatever I could find googling for NI.com as well. Mathworks technical support also wasn't able to help, so that is why I'm here, because I think it is a Labview issue. A simple C application can use the DLL just fine.


And how did you test that? A simple C application usually links to the DLL statically through an import library. This means the DLL is loaded at program start, then stays in memory as long as the application is active, and when the application terminates, the DLL is also unloaded by Windows.

 

In LabVIEW this is usually quite different. Because I never used Matlab DLLs from within LabVIEW, I'm not exactly sure about the specifics of integrating such a DLL. But if you use the Call Library Node (CLN), the DLL gets loaded for every Call Library Node that calls into that DLL at the time the VI containing the CLN gets loaded. The first load will actually load the DLL, all subsequent loads will increment a reference counter for that DLL. When a VI containing a CLN is unloaded, LabVIEW will also unload the according DLL, which decrements the reference count and if that reaches zero, Windows will unload the complete DLL.

 

During final unloading of the DLL, the DLLMain() function is called by Windows with the selector DLL_PROCESS_DETACH. And here things get interesting. If this function does something bad (illegal memory access or something) it will cause an error or in some cases a complete crash of LabVIEW, when the DLL was referenced through the CLN.

 

In your command line executable case, if the DLL causes an exception during process termination, you normally won't see any error indication, since Windows sees that the process is already terminated anyhow and won't pop up any dialog to prompt you if you want to kill the process or continue to terminate it, because there is no real difference to choose from between these two.

 

In order to simulate how it works in LabVIEW, you would have to not use the import library in your linking stage, but instead do an explicit LoadLibrary() on program start. then some GetProcAddress() to get a function pointer and call those functions though that pointer, and at some point before you actually terminate your program, call FreeLibrary() for that handle as often as you called LoadLibrary() if you called this multiple times. Only when this doesn't show the problem you observe in LabVIEW, can you conclude that LabVIEW is doing something illegal. Explicitly loading and unloading a shared library is a legal operation, and if the DLL can't deal with that properly, it's the fault of the DLL, not the application trying to load and unload the DLL explicitly.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 4 of 15
(6,086 Views)

Thanks for the lengthy response, it gives me a few things to think about. I am pretty confident that the behavior of the DLL is not at play, though I respect your comments about the differences with respect to how the libraries are loaded and unloaded. I like the idea of trying to mimic the approach that LabVIEW uses to try to confirm the issue. In the previous discussion on crashing libraries, one person had mentioned (perhaps that you hinted at) that LabVIEW loads the DLL when the VI is loaded. However, if you call the VI that contains the DLL by reference, then LabVIEW will not load it until that call by reference occurs, and should unload it when that reference is closed. I haven't tried that, so I will add that to the list of things to try.

 

I do suspect that the exception is caused when the DLL calls the MATLAB libraryTerminate() function (I uncommented my DLL code calls line by line until the exception would take place). If I leave the MATLAB libraryTerminate() function commented out, LabVIEW can call the DLL without any issue the second and subsequent times.

 

I do suspect that there is some interaction with the Matlab Compiler Runtime that isn't playing nicely...something isn't loading or unloading correctly so I'm open to that as well.

 

As you said, mimicking the way the DLL is called in both directions will be key in understanding what the issue is. If you are interested, I could make the DLLs, C, and H files available or visible to see if I have made an obvious error in my coding, which is entirely possible.

0 Kudos
Message 5 of 15
(6,082 Views)

So I managed to get my regular C application to crash, which surprisingly, is a good thing (TM). I have something to work on, including trying a few more things you suggested.

0 Kudos
Message 6 of 15
(6,077 Views)

How would I go about dynamically loading AND unloading (forced if needed) a VI calling a DLL? It appears there are issues with the underlying MATLAB runtime that dislikes re-initializing the application after termination. Since the C application works fine, I can safely assume that would you indicated is occurring, that the DLL is called at load time, and not unloaded until the application ends. The crash I managed to recreate was initializing and terminating the runtime more than once in a single application execution. The is likely the same reason that LabVIEW is crashing, as it loads the DLL the first time the VI is called/put into memory, but it never releases the DLL until LabVIEW is fully closed.

0 Kudos
Message 7 of 15
(6,067 Views)
Solution
Accepted by topic author CanadaGuy

Do you really need to terminate the runtime after each call?

 

Why couldn't you export a separate initialize() and terminate() function from your wrapper DLL and let your application call those explicitly on startup and termination (and remember that after calling terminate() you need to restart LabVIEW?

 

If the Matlab runtime does require a complete unload and reload of it after a terminate call, that is a bug in the runtime DLL, but since you have a wrapper DLL you can do a lot of customization when you call the initialize and terminate functions. 

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 8 of 15
(6,060 Views)

 

duplicate post after receiving an error when trying to  submit the response

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 9 of 15
(6,058 Views)

Yeah, I'll talk to Mathworks now that I understand the issue a bit more. Being able to fully unload the DLL without closing LabVIEW would be nice, but I'm exploring other options like using the .NET or COM object dlls. They are slightly slower I think, but may be worth the minimal headache.

 

Thanks for the ideas.

0 Kudos
Message 10 of 15
(6,045 Views)