04-15-2020 09:53 AM
Thank you for the reply. Can you exit labview properly after running it? I have tried the constant C string pointer, and the function works as expected, i just can't exit labview after running it.
04-15-2020 09:54 AM
Just kidding, it hangs. 🙂
04-19-2020 07:34 AM
Still working through this. The developer has been extremely helpful and has been trying to help me out on this. I now have a function that i can call that cleans everything up and i can exit LabVIEW without error. He tried adding the same cleanup to DLL_PROCESS_DETACH in the dllmain so that an explicit call would not be needed, but LabVIEW still crashes when i try and exit, which was a little surprising.
I also was wondering how to properly use the Unreserve callback parameter? I noticed that if i use the cleanup function call here, i don't have to explicitly call it, whenever i close LabVIEW. Is this it's intended use?
Thanks!
04-19-2020 09:59 AM
Well, Microsoft does document that you should not attempt to do certain things in the DLLMain processing of DLL_PROCESS_DEATTACH. Among other things calls to FreeLibrary() to unload other DLLs is a VERY bad thing to do since Windows holds a Loader semaphore during the unloading of a DLL and trying to unload other DLLs during this can have very bad effects, including crashes or mutual exclusion locks, which basically is a lockup.
The Unreserve callback would be a possible approach. You do need a function prototype that takes exactly one pointer sized variable by reference. I do think that the callback name for these functions is kind of misleading, but that's maybe just me.
The Reserve function is called when the VI containing the CLN is loaded into memory while the Unreserve function is called when that VI is unloaded. The Abort function is called when the LabVIEW hierarchy is aborted by the user.
The general idea is that the function assigned to Reserve Callback allocates a memory buffer to store information for the particular instance of the CLN. You then can pass this pointer to the DLL function as a special parameter (InstanceDataPtr) that won't be ccessible on the diagram as a terminal. The Abort and Unreserve callback also receives this pointer and the Unreserve function should then deallocate it.
You also can just call the Unreserve function of course which will receive an uninitialized pointer (probably a NULL value) as the Reserve function never was called to allocate one. Whatever you do inside the Unreserve function is basically executed by LabVIEW during the unloading of the VI.
The three functions together are helpful if you have a DLL call that could take quite long and you want a way to make it abortable. In Reserve you allocate a structure to store some synchonization objects such as an event or semaphore or similar. You then can pass this pointer to the actual function which monitors the event. In the Abort callback you trigger the event and the actual function on receiving that event then aborts its internal processing and returns to LabVIEW. That way the DLL function is abortable and you would not get the Resetting VI hierarchy dialog while LabVIEW waits for the synchronous DLL functions to return control back to the LabVIEW diagram.
There are also other possibilities such as using it as a sort of overlapped structure. The function would then not perform the whole operation but instead return with a special status indicating, operation still in process. The LabVIEW diagram could then do some other things and loop back to call the same function again, using the InstanceDataPtr. The function can then store management data to maintain its internal state between calls in the memory that this pointer points at. In this way the function can always continue where it left off to return control back to LabVIEW.