LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Pointer to LabVIEW Array

LabVIEW memory management question:

Question Part 1: When I write a C .dll that takes a LabVIEW array, LabVIEW passes a pointer into LabVIEW's memory to the array to C.  Can C return the pointer to me (e.g., not the array I passed in, but it's memory location)?

i.e.: void GetNativeMemoryPointer(float *pointer, float *array);

where *array is my input array, and GetNativeMemoryPointer returns the pointer to this array on *pointer.

Question Part 2: What issues will I run in to if I pass this returned pointer to another .dll call.  What if this .dll call is in .NET? 

Concerns: How does LabVIEW hold this array in memory?  When I call GetNativeMemoryPointer, does LabVIEW make a copy and send this a pointer to the copy to the dll, or is the pointer to the original?  Will LabVIEW ever "move" the original, e.g., will my pointer become invalid after some time?

Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 1 of 9
(5,455 Views)
Part 1: I must confess that I don't understand your question. Pointers and arrays are very closely related in C so I'm not following the sequence. So I don't know if the following applies, but here is a possible answer...
 
The pointer to a LV array that is passed to a call library node is valid ONLY during that call. Once the call to the DLL completes, you should consider that pointer value invalid. You can, of course, make a copy of the array and return a pointer to your copy - but LV won't know what it is. It definately won't show up in LV as an array. However, you can pass that pointer to the copy around to other DLLs as much as you want.
 
* Don't forget to free the copy. If you make a copy of the array, you own it - therefore you must free the memory of the copy at some point *
 
 
 
Part 2: Easier to answer.
 
* If you want LV to convert your pointer to a LV data type (such as a LV array): Take a look at page 2-4 in the "Using External Code in LabVIEW". In almost all cases we do not support pointers. The only exceptions are the ones shown in the Call Library Node configuration. For arrays, notice that if you want to return an array to LV, we have our own defined data types for this - read up on the CIN section for more information.
 
* If you want to return a pointer than LV just messages to other DLLs: No problem. Put the parameter to the routine as a pointer to integer (or a return value of type int). Thus your pointer is an integer as far as LV is concerned. When you pass it to another DLL, we'll pass the exact same value to the DLL - thus the pointer is never modified or the data touched.
 
Did this help?

Message Edited by Lycangeek on 08-10-2005 02:12 PM

Message 2 of 9
(5,431 Views)
Well, I believe you have answered my questions, but let me clarify just in case.  We are basically looking for a way to get a large block of data out of .NET without having to move it one element at a time (e.g., by indexing through an ArrayList).  The most efficient way would be to pass a pointer to a LabVIEW array into .NET, let .NET populate the array, then have LabVIEW operate on it (similar idea as to passing an array out of a Call Library Function node).  The jist of the question is how to get a native pointer for the LabVIEW array into .NET, as LabVIEW hides the details of this when done in the Call Library Function. 

One roundabout way might be to allocate an array in LabVIEW and pass it via pointer/handle into a Call Library Function.  The Call Library Function could then report back to LabVIEW what the native pointer memory address was, and LabVIEW could pass this on to .NET and .NET could do its thing.  However, your previous comments indicate that the pointer LabVIEW generates for the Call Library Function becomes invalid as soon as the DLL has completed.  So if we passed this to .NET, and .NET tries to write anything to it, LabVIEW will likely dump when .NET starts writing to this memory location.

Oh, well.  Guess we are writing more C code.
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 3 of 9
(5,423 Views)
Yes, the issue with passing an array from LV into a Call Library Node is that you cannot resize in the incoming array. You could use the CIN library calls to return an array to LV, but that will result in a copy operation. The arrays in LV are not C arrays - so you can't just give a C style array pointer to LV and have it show up in the diagram as an array.
 
But the idea of returning the pointer to the .NET data (properly pinned if it is .NET memory and not a simple malloc) and then writing .NET accessor methods is a tried and true method. For example, our own IMAQ libraries (image acq and processing) work by having the image in memory on the diagram as a refnum - not an array or other sort of data type.
 
Note that one mechanism is to have your .NET assembly expose a method that returns to LV a .NET array (not an array list - that is a collection class not an array). We will automatically copy this into a LV array - again it is a copy but allows you to avoid a lot of CIN code. Now, as you have mentioned, this can be very slow in LV 7, but the Constellation performance, especially for arrays of primative types, is VERY fast.
Message 4 of 9
(5,416 Views)
So what you want is to allocate array memory space by passing in a blank array into the DLL with a lenght of the data allocated and what you want to return is not the array value but a pointer to that array?  I think I understand this.  You should be able to create a pointer to the array in C and then return a numeric value in you call library function that is a pointer to your variable that you created.  Now the question is what do you want to do with this pointer.  Do you want to make another call to fill the array with the data? based on the pointer?
 
 
BJD1613

Lead Test Tools Development Engineer

Philips Respironics

Certified LV Architect / Instructor
0 Kudos
Message 5 of 9
(5,413 Views)

what kind of array are you passing into your call library function.  I have found that the easiest way to pass arrays in and out is just using a byte array.  Allocate 2K or something like that as your size.  That should give you alot of room to put data in.

 

 

BJD1613

Lead Test Tools Development Engineer

Philips Respironics

Certified LV Architect / Instructor
0 Kudos
Message 6 of 9
(5,411 Views)
Yes, that's the general idea, and I wish to pass this resulting pointer into a C#/.NET call next to populate the array.  The deeper question I had is that since LabVIEW is acting as it's own memory manager, I assume it could at any time move this array to a different memory location.  It would be a reasonable assumption that LabVIEW would "lock" the location of this array within its memory space while the C dll is running, but as soon as the dll is done, it would "unlock" it and allow it to move around.  If this assumption is true, then the pointer could go invalid at any time after the dll is complete.  If it is false and the memory location is static, then I can pass pointers at will (well, within the normal caveats of pointers in C++).

However, as Lycangeek indicated, the pointer to the LabVIEW array goes invalid as soon as the dll the pointer was created for has completed execution, so it is somewhat a mute point. 

Message Edited by Joe Gerhardstein on 08-10-2005 03:57 PM

Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 7 of 9
(5,407 Views)
We are passing mostly 4-byte floats.  A typical array size would be 102400 elements.  I may have dozens or hundreds of these in memory at any time, so I need to be relatively stingy with memory (and hence also my interest in performing the exchange of data between LabVIEW and .NET efficiently).
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 8 of 9
(5,403 Views)
I think we are all on the same page, but you know me...I just gotta go on and on and on... 🙂
 
If you return data into a LV data type (such as using an array in a call library node), LV makes no guarantees about the pointer once the DLL returns. For your information, this is because we have our own data structure system that may or may not require coverting the DLL data into a LV structure - this will obviously change the address of the data. Also, remember that LV data types on the diagram can be copied when the wire branches, when a subVI is called, etc. We try to be very efficient about this so we don't copy when we don't need to, but this is a common "advanced performance" talk that is given.
 
Go to Tools->Advanced->Show Buffer Allocations and we will put a little dot everywhere memory is being allocated. Sometimes this is a "first time allocation" but it can also be due to a copy.
 
So - no, memory locations are not static.
 
It is a completely different issue if you are returning a pointer to LV and LV doesn't need to do anything with that pointer other than carry it around and give it to other DLL calls. That is where you tell us the pointer is really an integer and let the DLLs cast it back and forth. There you are completely safe - but obviously can't access the data directly in LV - you must create access methods.
 
Message 9 of 9
(5,395 Views)