10-21-2008 03:09 AM
Hey everyone,
I'm learning how to interface LabView with a DLL, which uses the manager functions to create LabView types. Currently I want to return a selected String from an Array of Strings passed to LabView. In this test I want to explicitly create a new string in the external code. So, I have created the follwoing C++ code:
void element(TD1Hdl list, int32_t index, LStrHandle *element) {
LStrHandle h = (*list)->elt[index];
// maybe resize instead of create new?
LStrHandle newHandle = (LStrHandle)DSNewHandle(sizeof(int32) + (*h)->cnt);
(*newHandle)->cnt = (*h)->cnt;
MoveBlock((*h)->str, (*newHandle)->str, (*h)->cnt);
(*element) = newHandle;
}
Note the pointer to the handle, and I assign it in the end. I wired it up like below:
Note that nothing is going into the 3rd parameter.
now my question is:
- Is this possible? What does LabView do with the 3rd parameter (pass pointer to handle being NULL, or create default)
- Is my C code safe (apart from being able to specify an index that doesn't exist).
Thanks in advance!
Vincent
Solved! Go to Solution.
10-21-2008 03:46 AM
10-21-2008 05:04 AM - edited 10-21-2008 05:05 AM
Hi, Vincent,
As far as I can understand, you don't need to take care about creating new handle, because LabVIEW will do it for you (otherwise you will be responcible yourself for releasing allocated resource).
But you should set the size of the handle.
Something like this:

best regards,
Andrey.
10-22-2008 04:48 AM
10-22-2008 06:27 AM - edited 10-22-2008 06:28 AM
Hi, in general you don't need to create handles, if they already created in LabVIEW outside of your code.
In some cases its required, for example, if you need to copy arrays of string, then you need to create handle for each destination string:

Also you will need to create handles in situations when LabVIEW-generated DLL will be called from non-LabVIEW application. Then your application should take care about allocating resources, which will be passed as parameters to the LabVIEW-DLL.
read here a little bit:
Andrey.
PS
But if you can avoid handle allocation, then I will recommend to avoid it. For example, try to add some elements to destination array in the example above, then run code in cycle - you will get memory leak.
10-22-2008 07:35 AM
I created sort of similar code as you showed. In what way does the code you mentioned create memory-leak? Are the string handles created in the DLL code not cleaned up correctly? I'm using quite a bit of this kind of code in the DLL I'm writing, and it should be robust.
The only alternative I know against creating handles is the three-phase DLL invocation (1 - DLL: request required size, 2 - LV: allocate buffers, 3 - DLL: fill buffers), but that was hard to manage and created ugly code. Besides it is possible that data is added between invocation 1 and 2 by another process, so I should add additional checks for that.As an alternative to that I could cache te results from invocation 1 in the DLL, but then if step 3 never occurs memory stays allocated for the (sometimes large) resultsets
I find using the labview manager functions create much more transparent code, was it not that it apprarently easy to create memory leaks. So, the statement I made earlier is correct: Handles created in DLLs are not cleaned up by labview? I could not deduct that from the link you provided.
10-22-2008 09:18 AM - edited 10-22-2008 09:19 AM
The memory leak occurred if you will run the following code:

So, in this case you should check if handle already exists, do not create new, but only resize it.
In general you should create new handles usually for array elemenths (if your array elements are strings or clusters, but not numerics - there special function for resizing numeric arrays).
As far as I can understand, you don't need to release these handles, because LabVIEW will do it for you (anyway you can easily check it - just run your code in the cycle and check the memory usage).
But personally I feeling a bit dangerous to calling DSNewHandle without DSDisposeHandle. Probably you can play with DSCheckHandle before DSCreateHandle, or use DSCopyHandle for trasferring new created/resized array to the destination, then you can release your temporary created handle.
Note, that National Instruments says in Help following: "...When returning a new array from a DLL, you must allocate memory for the array in LabVIEW. The easiest way to do this is to input an array of a known length into the Call Library Function node that is at least as large as the expected resulting array being returned from the DLL..."
and then example from NI:

Andrey.
10-22-2008 09:47 AM - edited 10-22-2008 09:48 AM
Thanks! I understand. The array initialized by LabView (ArrayDst) also has handles to strings, but I just overwrite those, without disposing them, thus creating memory leak.
Unfortunatly I do not know the size in advance, but I will do my best not to create any of those leaks 🙂
Thanks again for your replies, they have been very helpful.