10-15-2024 10:25 AM - edited 10-15-2024 10:33 AM
Help!
Using LabVIEW 2012 (I know, old, but there are reasons...), when I call a driver DLL I get Error 1097.
We don't have target hardware yet (it will be a while), when I call the DLL initialisation function the DLL status output returns 'not initialised', but there is no error, as I would expect.
Error 1097 is returned when I subsequently try and interact with the device, for instance calling the DLL out8 function.
Could the exception be raised because target hardware isn't present? I thought Error 1097 was corruption due to incorrect DLL call parameter types?
I've tried changing the calling convention between stdcall and C, and set the parameters to those stated by the header file, but Error 1097 is still returned.
I've also used the LabVIEW 'Tools> Import > Shared Library (DLL)', the resulting lvlib does the same (Init and exit works, but all other DLL functions fail with 1097)
I've attached the lvlib and included the header file with it.
Any thoughts please?
Thanks
Solved! Go to Solution.
10-15-2024 10:37 AM - edited 10-15-2024 10:40 AM
Error 1097 means the DLL did something that it should not have done as far as LabVIEW can know or it generated an exception. General protection fault errors are also exceptions, unless Windows decides that the error is so grave that the application process has forfeited every right to live and simply terminates it immediately.
Wrong parameter configurations can be one of the reasons but it could be just as well that the DLL simply assumes that if the caller is bold enough to call subsequent function, he made sure the initialization call was successful and therefore simply tries to access the device that never got initialized. Only the documentation (unlikely) or the original developer of that driver can tell you that.
10-15-2024 10:56 AM
Thanks - so is there no alternative but to wait until the hardware device arrives - so I can call DLL initialise and then issue subsequent DLL commands?
10-15-2024 11:08 AM - edited 10-15-2024 11:16 AM
Only the original developer can tell you if it is safe to call those functions after an unsuccessful initialize. If it was my driver it would be, but they wouldn’t do anything beyond returning an error code. But there are many programmers out there who know enough to be dangerous but not enough to know that they are dangerous.
it could of course be also simply an error in how you configured the Call Library Node. Impossible to say anything specific from a distance. As I stated many times already, the Import Library Wizard is not a magician. But it would require magic abilities to create a perfect import library from just a C header file. If you can’t create the VIs with the Call Library Nodes correctly yourself, you can’t review the VIs created by the Import Library Wizard to be correct and modify them to be correct and simply end up with a crash generator in most cases.
10-16-2024 01:24 AM
Thankyou for your reply.
You seem to have misread my original post. I was not relying on the NI 'wizard' to do the job for me - I said that the result of the NI wizard was the same as my manual use of the DLL function call.
I had been hoping that someone with more experience than I would take a cursory glance to see if my DLL call parameters were correct, for this purpose in my post I included the lvlib, the DLL and header.
I have written plenty of C over many years, but I have never had the need to call DLL's from LabVIEW.
I had been hoping for help rather than sagelike comments telling me what a poor job the wizard does 😞
10-16-2024 03:56 AM - edited 10-16-2024 04:01 AM
I have to apologize for the harsh tone. I did respond from my phone and as such not only didn't have the ability to look at your attached archive but actually missed the fact that there was one attached. Unfortunately it is very common here to post such requests and somehow expect that the readers will be able to magically give sound advise only based on some vague explanation of the problem. And in the case of the Call Library Node to be utterly surprised or even upset that it can't create a perfect import library.
I now took a look at your file and while I didn't check every single VI, the function API of that "driver" is really trivial and should be easily possible to handle without even having to resort to bothering the Import Library Wizard.
So the next step was to look at the driver DLL itself in a disassembler and I can verify that the functions should be called with C calling convention. But boy is that piece of software nasty. The programmer of that obviously did know quite enough to be very dangerous. The Initialize function does open a named memory mapped view to a kernel object created as "Global\arstech". If successful it then goes and stores the pointer to that in a global variable.
And now comes the bummer: every other function simply loads that global variable and references it without even checking if it was successfully initialized. So yes this driver is BAAAD. A clear case of a programmer who knows enough to be really dangerous but not enough to know that they are.
I assume that the full driver for this device also installs a kernel device driver that creates that memory mapped view. Maybe if that driver was installed on your system, the DLL functions would not crash since the opening of the memory mapped view "might" succeed and simply return an error. But maybe the kernel driver is programmed in a similar hazardous way and you only would move the crash from user space into kernel space and that would be A LOT more unpleasant than a returned error 1097 from the Call Library Node.
How to deal with this in LabVIEW? Well, it is not likely that the device manufacturer documents the memory map interface to their device driver. Reverse engineering that from the DLL disassembly code could be possible but only as last resort and if someone wants to throw a lot of money in this. If the memory mapped interface was properly documented, it would be possible to call in LabVIEW the according Windows APIs directly to access this interface and properly error out when that does not succeed. A bit of work, but better than this piece of DLL trash for sure.
The poor mans approach would be to actually write a slightly more intelligent wrapper around these DLL calls. I would put it into a LabVIEW class. Have in the private class data a boolean or even better an integer that you set to true or a magic value when the Initialize function executed successfully and only then. In every other class method check this value to be equal to that magic value and only call the DLL function if it is. In the unitialize function reset it to false or 0. It's not idiot proof and even less engineer proof, as anyone can branch the class wire away before calling the uninitialize function and it will still have the magic value in the private class data. But it's at least something and a bit of responsibility can be also expected from the LabVIEW programmer who uses these functions.
10-16-2024 07:55 AM
Rolf, Thank you for taking the time to run the DLL through a disassembler. That has helped me a huge amount.