From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Call library function to access a dll crashes labview 2020

Solved!
Go to solution

I am at my wits end with this software. Have been previously working in Labview 2015 64bit without a problem and recently upgraded to Labview 2020 but for some reason I cannot use previously developed software to control my hardware. I am using Call library functionality to access opal Kelly frontpanel dll but when I try a particularly function 'openbyserial' the whole thing crashes. What is different between Labview 2015 and 2020? I have ensured that all dependencies have been included and have performed several uninstallations and reinstallations in case I have missed something. Whilst I understand I am accessing 3rd party software, this should be trivial with Labview yet it is not. 2011 - 2015 has been fine yet 2020 isn't. Why? 

0 Kudos
Message 1 of 23
(4,035 Views)

Hi simy,

 


@Simy25 wrote:

Have been previously working in Labview 2015 64bit without a problem and recently upgraded to Labview 2020 but for some reason I cannot use previously developed software to control my hardware.


Did you upgrade to LV2020 64bit or 32bit?

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
Message 2 of 23
(4,026 Views)

I upgraded to 2020 64bit. I would have received an error if I tried to use a 32bit dll anyway. There is no apparent reason why this should not function unless the way labview handles third party dlls have changed. I have spent the best part of 2 days performing reinstallations, generating new VIs using the import dll function and writing basic VIs to follow flow. I don't even receive an error message...Labview just hangs and I need to kill the program via task manager. 

0 Kudos
Message 3 of 23
(4,004 Views)
Solution
Accepted by topic author Simy25

LabVIEW has not changed in how it handles DLLs. But your Call Library Node may have been configured all the time wrong and for some reason it worked before.

 

Possible reasons are many:

 

- Output buffers that are not large enough preallocated. The function may have written less data into that buffer before so it worked then with a smaller buffer, or it may have overwritten beyond the buffer end anyways but didn't corrupt essential data that send LabVIEW immediately in a misfit.

 

- You may have handle datatypes configured as 32-bit integers but that are under 64-bit full 64-bit integers. As long as the value of such a handle is smaller than 0xFFFFFFFF it happens to work all fine as the numeric value the function returns is truncated to 32-bit but no data is lost. When passing the handle back to another function the 32-bit value gets size extended to be passed as 64-bit integer on the stack again, as the smallest parameter size is basically 64-bit anyways. Such parameters need to be configured in the LabVIEW Call Library Node as pointer sized integer and the control value on the LabVIEW diagram needs to be a 64 bit integer. This way no data gets lost when the handle value exceeds the 32-bit limit.

 

Hmmm the Opal Kelly C++ API definitely can't be called by the Call Library Node so you must probably be calling the .Net API.

With that it is pretty hard to see how LabVIEW could do something wrong. The .Net API should simply be fully self declaring and the LabVIEW .Net nodes should just use that assembly declarations.

 

Maybe you can show the code you are actually using.

 

Ok, I found a header file and it seems the DLL also export standard C wrapper functions for the classes.

 

AND yes, there are a lot of HANDLE types which are all declared as void*. If your Call Library is not configured to treat them as pointer sized integer OR you are not using a 64-bit integer to pass them around on the LabVIEW diagram, you were simply lucky that it did not crash before. Apparently all the objects were always allocated below the 0xFFFFFFFF address before but with newer LabVIEW versions loading more extensions and using more memory it can very easily happen that the object allocations move beyond that address. And then you get BAM if they are not consistently treated as 64-bit entity throughout your program. Nothing really that LabVIEW does different, your library simply was never correct to begin with.

Rolf Kalbermatter
My Blog
Message 4 of 23
(3,970 Views)

Hi Rolf,

and thank you for the suggestions. I have checked that all the connecting variables and pointers -they are all at the correct settings and I provided adequate buffer output sizes to the Call Library Nodes. I think it may actually be due to the installation of Labview 2020. I have now performed 3 uninstallations and reinstallations but still no joy. I managed to scale back the Opal Kelly based program to do a simple 'frontpanel_construct' then 'frontpanel_destruct' with the dll (see attached) and was able to get an error log (see attached) when Labview froze. Seems to be a problem someone has come across before but the solution of simply moving to 32bit labview is not a viable option for my application. Since uninstalling and reinstalling labview doesn't work, if there is a simpler solution than reinstalling windows I would be very grateful. I have also included an example vi (BasicOpalKellyTest.vi) and 64bit Frontpanel.dll. 

Thank you very much in advance and best regards,

Simon

 

0 Kudos
Message 5 of 23
(3,911 Views)

If you could backsave your VI to 2018 and 2019, it would help.

Rolf Kalbermatter
My Blog
0 Kudos
Message 6 of 23
(3,903 Views)

Dear Rolf,

apologies for the delay in getting back to you and thank you very much for your help. You were indeed right with your previous comments. I had neglected to convert one of the handles from 32bit to 64bit and therefore the handle was not passed on. Once I implemented this for all VIs the program worked as expected. It is strange that there were no issues for Labview (64bit) from 2012-2015 but I am very grateful that your solution worked. I will mark your previous comment as the solution and thank you again for taking the time to reply. 

Best regards,

Simon 

 

 

0 Kudos
Message 7 of 23
(3,859 Views)

@Simy25 wrote:

It is strange that there were no issues for Labview (64bit) from 2012-2015 but I am very grateful that your solution worked.


Not really strange. These handles seem to be directly pointers to some data structure that manages various attributes for this device. The memory layout of a process depends on many things such as number of loaded modules (DLLs) with their preferred load address, size of the code and loaded modules, etc. It is safe to assume that LabVIEW itself gets bigger with each version, as do the various modules it loads directly or indirectly. So your memory layout is definitely changing and the heap from which memory can be allocated for those data structures moves higher and higher. As long as the memory buffers are allocated beyond the 2/4GB linear address space, the pointer fits into 32 bit anyways, even if it is a 64-bit application. The higher 32-bits are simply 0. So while the DLL returns a 64-bit pointer that you told LabVIEW to stuff in a 32-bit integer this truncation is only a problem when the pointer happens to be above the 2/4 GB address limit. When this 32-bit integer is passed back to the DLL, it is always sign-extended to 64-bit since the stack needs to be 64-bit aligned.

 

Now if you happen to have configured that handle as 32-bit signed integer the problem already happens when the pointer is above the 2GB address limit, because after truncation of the higher 32-bit and interpreting it as 32-bit signed integer the address 0x0FFFFFFFF suddenly gets -1 when interpreted as signed 32-bit integer. When sign extending this to a 64-bit value, the value passed on the stack is 0xFFFFFFFFFFFFFFFF ... and BOOMM!

 

If you had configured it as 32-bit unsigned integer this would not happen since an unsigned integer when sign extended stays the same as there is no sign to convert. A problem only occurs when there is an address beyond 4GB. 0x100000001 after truncation gets 0x01 and when extending it to 64-bit remains 0x01, which is of course still a far cry from what it should be.

Rolf Kalbermatter
My Blog
0 Kudos
Message 8 of 23
(3,852 Views)

Hello,

I am having trouble in getting one of the function right. I am calling the library function of CP2112 from silicon labs.

So far I am able to execute the device open, read request function without any issues, but moment I call the GetReadResponse function the Labview crashes.

I have been trying for last two days but no success. I believe the parameters are set as per the API documentation.

Wish you could find the problem.

I am running the application in Labview 32 bit, the DLL is also 32 bit.

Attached the VI, DLL and the API doc.

 

Thanks

Shan

 

0 Kudos
Message 9 of 23
(2,494 Views)

@User002 wrote:

 

So far I am able to execute the device open, read request function without any issues, but moment I call the GetReadResponse function the Labview crashes.


That's because pretty much everything possible about that Call Library Node configuration is as wrong as possible. You can't just configure a pointers sized integer where the function wants to write data into. This buffer has to be allocated by the caller (this is your VI you are writing), and correctly passed to the Call Library Node so it can call the function with the right parameters on the stack.

 

Your Call Library Node needs to be configured with the second parameter as an uint32 passed as Pointer to Value. This is an enum with the values 0 to 3 so an 8 bit numeric is enough to represent it but since we don't know what C compiler is used to create the DLL we can't be sure that it won't try to write to the full 32-bit value by default. Not all C compilers will use the smallest possible unsigned integer type for enums.If you want to be fully safe that it always works you also would have to mask the returned value by ANDing it with 0xF to clear any potentially uninitialized higher significant bits in the 32-bit value.

 

The next parameter is a byte array. You need to configure this as such and pass the Data Pointer of it to the DLL function. This byte array needs to be preallocated and well with the same size as the Buffersize variable is indicating. The last parameter is correct but you should use it to resize the byte array after it exits the right side of the Call Library Node to the actual size the DLL function has written into.

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 23
(2,481 Views)