mooner Posted October 23, 2023 Report Share Posted October 23, 2023 How does LabVIEW get an image in memory. The pointer to the image in memory and the width of the image as well as the height are known. Which function should I call? Attached is a DLL prototype that outputs the pointer and size of the picture. I need to call the DLL to get the picture Quote Link to comment
Neil Pate Posted October 23, 2023 Report Share Posted October 23, 2023 (edited) I am definitely not an expert on this kind of stuff, but I think you would first "create" a datastructure big enough to hold your image in LabVIEW. The type does not actually matter as long as it is big enough (1 byte * width * height) and then pass that into your DLL call as the first input parameter, followed obviously by the width and height. After the DLL call the data should now have been copied into that datastructure (i.e. the wire itself will have the image on it). I get easily confused with pointers to pointers, so might have this completely wrong. Sorry I have not explained this very well. Can you attach your DLL? Edited October 23, 2023 by Neil Pate Quote Link to comment
dadreamer Posted October 23, 2023 Report Share Posted October 23, 2023 (edited) 7 hours ago, mooner said: The pointer to the image in memory and the width of the image as well as the height are known And what's the image data type (U8, U16, RGB U32, ...)? You need to know this as well to calculate the buffer size to receive the image into. Now, I assume, you first call the CaptureScreenshot function and get the image pointer, width and height. Second, you allocate the array of proper size and call MoveBlock function - take a look at Dereferencing Pointers from C/C++ DLLs in LabVIEW ("Special Case: Dereferencing Arrays" section). If everything is done right, your array will have data and you can do further processing. Edited October 23, 2023 by dadreamer Quote Link to comment
mooner Posted October 25, 2023 Author Report Share Posted October 25, 2023 On 10/23/2023 at 6:49 PM, Neil Pate said: I am definitely not an expert on this kind of stuff, but I think you would first "create" a datastructure big enough to hold your image in LabVIEW. The type does not actually matter as long as it is big enough (1 byte * width * height) and then pass that into your DLL call as the first input parameter, followed obviously by the width and height. After the DLL call the data should now have been copied into that datastructure (i.e. the wire itself will have the image on it). I get easily confused with pointers to pointers, so might have this completely wrong. Sorry I have not explained this very well. Can you attach your DLL? Thank you, your explanation is very clear. I have solved my problem so far and the solution is basically the same as you said. Quote Link to comment
mooner Posted October 25, 2023 Author Report Share Posted October 25, 2023 On 10/24/2023 at 1:04 AM, dadreamer said: And what's the image data type (U8, U16, RGB U32, ...)? You need to know this as well to calculate the buffer size to receive the image into. Now, I assume, you first call the CaptureScreenshot function and get the image pointer, width and height. Second, you allocate the array of proper size and call MoveBlock function - take a look at Dereferencing Pointers from C/C++ DLLs in LabVIEW ("Special Case: Dereferencing Arrays" section). If everything is done right, your array will have data and you can do further processing. Thank you very much for your reply. After your guidance, I re-learned the use of "MoveBlock" and found that this function is indeed a very powerful thing, and I have solved my problem by using it so far. Attached is a screenshot of my code, thanks again! Quote Link to comment
Rolf Kalbermatter Posted October 25, 2023 Report Share Posted October 25, 2023 (edited) 20 hours ago, mooner said: Thank you very much for your reply. After your guidance, I re-learned the use of "MoveBlock" and found that this function is indeed a very powerful thing, and I have solved my problem by using it so far. Attached is a screenshot of my code, thanks again! What does the documentation say about the pointer returned by the function? Is it allocated by the function? Is it a static buffer that is always the same (very unlikely)? If it is allocated by the function, you will need to deallocate it after use (after the MoveBlock() function), and the documentation should state what memory manager function was used to allocate the buffer and what memory manager function you should use to deallocate it, otherwise you create a memory leak every time you call this function. Ideally the DLL exports a function that will deallocate the buffer, still a usable solution is if they use the Windows GlobalAlloc() function to create the buffer in which case you would need to call GlobalFree(). Pretty bad would be if they use malloc(). This is because the malloc() call that the DLL does might be linking to a different version of the C runtime library than the according free() you will try to call in LabVIEW, and that is a sure way to create trouble. Edited October 25, 2023 by Rolf Kalbermatter Quote Link to comment
mooner Posted October 26, 2023 Author Report Share Posted October 26, 2023 6 hours ago, Rolf Kalbermatter said: What does the documentation say about the pointer returned by the function? Is it allocated by the function? Is it a static buffer that is always the same (very unlikely)? If it is allocated by the function, you will need to deallocate it after use (after the MoveBlock() function), and the documentation should state what memory manager function was used to allocate the buffer and what memory manager function you should use to deallocate it, otherwise you create a memory leak every time you call this function. Ideally the DLL exports a function that will deallocate the buffer, still a usable solution is if they use the Windows GlobalAlloc() function to create the buffer in which case you would need to call GlobalFree(). Pretty bad would be if they use malloc(). This is because the malloc() call that the DLL does might be linking to a different version of the C runtime library than the according free() you will try to call in LabVIEW, and that is a sure way to create trouble. Thanks for the heads up! Indeed the program was running with a memory leak. My code also needs to call the function where the DLL frees the memory. I tested it and the modified program does avoid the memory leak problem. Quote Link to comment
MikaelH Posted October 26, 2023 Report Share Posted October 26, 2023 Also try running the DLL in any thread. That will probably speed up the execution >100 times, but if the DLL is not thread safe you might get crashes. Quote Link to comment
Rolf Kalbermatter Posted October 26, 2023 Report Share Posted October 26, 2023 (edited) 1 hour ago, MikaelH said: Also try running the DLL in any thread. That will probably speed up the execution >100 times, but if the DLL is not thread safe you might get crashes. That is a tricky recommendation, as you explain too. Unless it is documented that the DLL or particular function is thread safe, I would normally refrain from calling the function in any thread. Also your claimed speed improvement is very off, especially in this case. The main time loss is when the LabVIEW program has to wait for the UI thread to be available for calling the CLN. This is at worst in the order of a few ms, typically even significantly below 1 ms. Compared to the runtime of these functions, which for the capture does a GDI bitmap copy and some extra shuffling to only get out the actual pixel data and for the MoveBlock(), which does a memory copy of a significant size, this delay of arbitrating for the UI thread is pretty small. It's likely measurable with the high resolution timer, but do you really care if this VI takes 25 ms to execute or 26 ms? Reentrant execution of a CLN gets really interesting performance wise when you have a short running function which is called over and over again in a loop. Here the overhead of arbitrating each time for the UI thread will be significant and can get even the single most dominating factor in the execution speed. There is one other aspect about not wanting to run a CLN in the UI thread. While LabVIEW is busy executing the CLN in the UI thread, this thread is not available to do anything else, including drawing anything on the screen and processing Windows events such as mouse and keyboard events. If the CLN takes a long time to execute (many 100 ms to seconds) the LabVIEW application will appear to be frozen during the call to this CLN (and in the worst case Windows will notice after several seconds that the event loop isn't polled for a long time and provide the user with a dialog suggesting that the application is unresponsive and should probably be shut down). Edited October 26, 2023 by Rolf Kalbermatter Quote Link to comment
mooner Posted October 27, 2023 Author Report Share Posted October 27, 2023 15 hours ago, Rolf Kalbermatter said: @Rolf Kalbermatter@MikaelH Thank you both for your suggestions. I'm not sure at the moment if this dll is thread-safe as there is no documentation on it. I'm using the UI thread to run it for now to be on the safe side. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.