Jump to content

DLLs that expect LabVIEW data to stay put.


Recommended Posts

I have a suite of compiled DLLs. One of them is essentially the "Load Data" function where you pass it arrays of values; the second is a "Compute" function, which uses the values you gave it earlier. However, the "Load Data" function isn't stashing away the data, but simply storing the array pointers for the "Compute" function. I need to arrange for LabVIEW to keep the data - untouched - and in the same place, between the calls to the "Load Data" and "Compute" DLLs.

I've tried using shift variables and global variables, but they appear to both cause LabVIEW to copy the array data and pass the pointer to the copy on to "Load Data", and then throw it away. So now when "Compute" is called, the saved pointer is to memory that may have been reallocated. *Crunch*. Time to restart LabVIEW.

I could do this in "C" with a "static" declaration (using memory from the data and/or heap, not the stack), but I'm still new to LabVIEW. I checked the existing threads and didn't see this question asked. Could somebody please advise?

Thanks,

Andrew

Link to comment

You cannot guarantee that memory block reserved by LabVIEW stays in the same memory position between multiple DLL calls. LabVIEW guarantees only that memory block stays in certain memory position for the time of the DLL call. To have a block of memory that stays in certain memory position, you need to reserve and release the memory within the external code.

Link to comment

I haven't tested if this will work, but there might be a possible (roundabout) way to do this if you have the Vision toolkit installed. There is a hidden subVI called "IMAQ Create&LockSpace.vi" in "Compatibility.llb" in the vi.llb -> Vision directory. From the description, it allows you to allocate an image with a fixed size in memory, ensuring that that memory space is always available. It's only supposed to be used in situations where memory constraints are tight, but I believe it may work for your situation. Just use this vi to create a memory space, typecast your data to a series of "pixels" that can be mapped to this place, and then use "IMAQ GetImagePixelPtr.vi" to obtain a pointer to that memory space for your dll call. As long as you can ensure that your data will never grow beyond the allocated size, I believe the memory location will stay constant.

Link to comment

QUOTE(Yuri33 @ Jul 8 2007, 11:46 PM)

I haven't tested if this will work, but there might be a possible (roundabout) way to do this if you have the Vision toolkit installed. There is a hidden subVI called "IMAQ Create&LockSpace.vi" in "Compatibility.llb" in the vi.llb -> Vision directory. From the description, it allows you to allocate an image with a fixed size in memory, ensuring that that memory space is always available. It's only supposed to be used in situations where memory constraints are tight, but I believe it may work for your situation. Just use this vi to create a memory space, typecast your data to a series of "pixels" that can be mapped to this place, and then use "IMAQ GetImagePixelPtr.vi" to obtain a pointer to that memory space for your dll call. As long as you can ensure that your data will never grow beyond the allocated size, I believe the memory location will stay constant.

A less costly and also platform independant way is to use a Call Library Node to allocate memory areas by calling into LabVIEW itself. Setting the library name to LabVIEW you can call all the exported LabVIEW manager functions that are documented in the External Code Reference Manual and that includes the LabVIEW memory manager that can do all this. Make sure to use C calling convention as that is what LabVIEW exports its manager functions as, and obviously configure the rest of the Call Library Node according to the documentation for the function you want to call.

Advantage is you don't need an (expensive) Toolkit installed and if you ever happen to have to move these functions to another LabVIEW platform this part will simply continue to work (the DLL part itself obviously not :). Don't forget to deallocate the memory poiunters after use obviously as otherwise you create memory leaks.

Rolf Kalbermatter

Link to comment

QUOTE(rolfk @ Jul 11 2007, 12:56 PM)

...use a Call Library Node to allocate memory areas by calling into LabVIEW itself...

What an excellent suggestion. I guess the following sequence needs to be executed for this particular task

  1. Reserve a block of memory referenced by a pointer p
  2. Copy content of a LabVIEW array excluding the size specifying bytes to the newly created block
  3. Call first proprietary C function and pass the pointer to this function
  4. Copy second proprietary C function and pass pointer p to this function as well
  5. Create a new array handle and copy the content of the memory block referenced by p to the memory block of this handle after the size bytes
  6. Set the size bytes of the array handle to the proper values

However I'm not sure if this task can be safely implemented within LabVIEW only. The set of memory manager functions is limited and pointer referencing and dereferencing is a challenging job within LabVIEW. Multiple calls to LabVIEW executable are not atomic in a sense that LabVIEW guarantees the memory buffers to remain the same for each call. As a result it's hard to properly manipulate LabVIEW array handles from within LabVIEW. Even when current version of LabVIEW doesn't make a buffer allocation in certain place, there is no guarantee that future version of LabvIEW will act the same way. I'm familiar with using LabVIEW memory manager functions in external C code and still this task seems challenging for me to complete using only calls to LabVIEW executable. On the other hand the task is relatively easy if one simply writes a few lines of C code and compiles that into a shared library (DLL).

Link to comment

QUOTE(Tomi Maila @ Jul 11 2007, 02:11 PM)

What an excellent suggestion. I guess the following sequence needs to be executed for this particular task
  1. Reserve a block of memory referenced by a pointer p
  2. Copy content of a LabVIEW array excluding the size specifying bytes to the newly created block
  3. Call first proprietary C function and pass the pointer to this function
  4. Copy second proprietary C function and pass pointer p to this function as well
  5. Create a new array handle and copy the content of the memory block referenced by p to the memory block of this handle after the size bytes
  6. Set the size bytes of the array handle to the proper values

However I'm not sure if this task can be safely implemented within LabVIEW only. The set of memory manager functions is limited and pointer referencing and dereferencing is a challenging job within LabVIEW. Multiple calls to LabVIEW executable are not atomic in a sense that LabVIEW guarantees the memory buffers to remain the same for each call. As a result it's hard to properly manipulate LabVIEW array handles from within LabVIEW. Even when current version of LabVIEW doesn't make a buffer allocation in certain place, there is no guarantee that future version of LabvIEW will act the same way. I'm familiar with using LabVIEW memory manager functions in external C code and still this task seems challenging for me to complete using only calls to LabVIEW executable. On the other hand the task is relatively easy if one simply writes a few lines of C code and compiles that into a shared library (DLL).

While in theory your conerns could be right they don't have to be for two reasons.

1) As long as you do nothing with a wire (and data dependency can ensure a variable stays put in memory until after a certain point) LabVIEW does not deallocate or move it. In fact all diagram data (except paths) are stored as DS (Data Storage) memory contrary to AZ (Application Zone) memory. The distinctions (although I believe in practice this makes no difference on most modern platforms anymore as the memory virtualization of modern 32bit CPUs completely hides the physical memory management of the CPU from all applications) is that AZ memory handles can be locked but don't need to be while DS memory handles always are locked. A locked handle means that the memory manager will never move around your memory block while you do other things in LabVIEW, unless you explicitedly use memory manager functions to deallocate or resize such a handle. Pointers are by their nature non relocatable unless explicitedly reallocated.

2) The memory manager has some very powerful functions that can directly move between pointers and handles and that ensure that the operation is properly protected in the context of the LabVIEW execution system. But even without this, as long as you make sure that no other LabVIEW functions can concurrently operate on a handle whose pointer you treat with your direct DLL magic functions, you can be sure to be safe. And by the way this is why LabVIEW has to and does make data copies on branching wires when more than one function can possibly modify that data.

Rolf Kalbermatter

Link to comment
  • 4 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.