LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

CIN readback of an array given its pointer -- possible without copying?

Well, it seems at this point we are mostly in agreement about the major points, and simply disagree about the danger of my method. Ultimately that issue comes down to the experience of the developer, as you pointed out, and the customer and lifetime of the application. For most of my work, the customer is me (in the lab) and the application lifetime is short (long enough to get the data).

A few minor points to clear up:


@rolfk wrote:
While you may feel this is logical and anything else would be stupid I find this a remarkable piece of optimization which almost certainly wasn't present in earlier versions maybe even in 6.x but quite sure in 5.x. I don't say your method wouldn't seem to work in those versions, but in order to be able to reuse the array buffer in the next iteration LabVIEW would simply have created a new array buffer in Array Subset and copied all the data necessary, only to create even a new copy for the front panel control in really old versions.


The Array Subset optimization is impressive. But, as I mentioned in my last post, that's not what I'm relying on. The optimization, if you can call it that, that I'm not impressed about is the non-copying of an "unmodified" buffer that is still in use.

I chose the Array Subset simply to have some sort of operation done on the array. It was a rather arbitrary choice as far as I was concerned, and it was a bad choice, in retrospect. I should have multiplied it by two, or something. Better yet, multiplied a subset by two.

Well it is not irrelevant as far as the original poster was concerned, since it was exactly this copying of data he wanted to avoid.


It was my impression that the original poster was trying to avoid a copy of the entire buffer with each read. He would accomplish this by having the framegrabber write directly to a LabVIEW buffer associated with an array handle of some sort. What he wished to avoid was passing the framegrabber a private buffer which was copied into a LabVIEW buffer with each iteration. Copies, either in part or in full, that were necessary to process the data were not this issue.

Jason
0 Kudos
Message 21 of 25
(1,179 Views)
Hi Jason and Rolf,

> He seems to have lost interest in our little discussion, anyway. Sigh.

not at all! I was away for some days. It will take me a little to process all that you added.
Thank you for keeping the thread alive,
Enrico
0 Kudos
Message 22 of 25
(1,164 Views)
I started getting back to the business. Since Jason's solution of message #14 works for me, I started adapting it to my needs, breaking the relevant pieces in useful sub vi, etc. The main point there is that my grabber routine needs the pointer to the buffer to start with, not the pointer to its labview handle. It is fine for me to read the buffer using the labview wire, to free the buffer afterwards using the handle, but I need a dull pointer to pass to the grabber DLL, along with the hope (reasonable, I in the present version, I understand), that Labview dosn't relocate this buffer. Well, I thought this simple modification (along with the corresponding modification of the library call node) should have worked:

LVARRAYPOINTERDLL_API int CreateBuffer(Data** ppData, unsigned char* pBuffer, int pointer, unsigned int size)
{
*ppData = new Data;
(*ppData)->buffer = pBuffer;
(*ppData)->size=size;
(*ppData)->call=0;
pointer = reinterpret_cast (pBuffer);
return 0;
}

However, this always returns me 0 in pointer. Same with other variations like

pointer = (int) pBuffer;
pointer = (int) &pBuffer;

to compensate for my C incompetence. What am I doing wrong?

Enrico
0 Kudos
Message 23 of 25
(1,159 Views)
Hi Enrico,

It's not clear to me from your last message exactly what you're doing. You stated that you were using my example from message #14, which is an all LabVIEW example in the important parts. Yes, there is some C code, but that is merely to emulate your framegrabber routine. Following my suggestion, no C code shoudl be necessary. Then, you go on to show how you've modified my DLL. Why?



@enrico Segre wrote:

breaking the relevant pieces in useful sub vi


Be careful when breaking things into subVIs as you may cause more buffer allocations at the terminals which could be deterimental to this project. You can, definitely avoid any such problems if you make the relevant VIs subroutines (VI Properties->Execution).

It is fine for me to read the buffer using the labview wire, to free the buffer afterwards using the handle, but I need a dull pointer to pass to the grabber DLL, along with the hope (reasonable, I in the present version, I understand), that Labview dosn't relocate this buffer.


By configuring the framegrabber function (the initialize one, that is) to take an Array pointer to data, as in my example, you should be passing the dull pointer. (I assume by "dull pointer" you meant "Not a handle?")


However, this always returns me 0 in pointer. What am I doing wrong?



pointer is a pass-by-value parameter, and as such cannot return a value. You probably want something like:

int CreateBuffer(..., int* pPointer)
{
...
*pPointer=(int)pBuffer
}


and make sure to configure the DLL call appropriately in LabVIEW so that pPointer is a pass by pointer variable.

Jason
0 Kudos
Message 24 of 25
(1,137 Views)
Thanks Jason,

> int CreateBuffer(..., int* pPointer)
> {
> ...
> *pPointer=(int)pBuffer
> }
>
> and make sure to configure the DLL call appropriately in LabVIEW so that pPointer is a pass by pointer variable.

Precisely that. Your last message gave me the missing clue. Thanks a bunch for correcting my C syntax. The application is up and working now, and I see the expected performance gain with respect of my original, "wasteful copy' solution.

Of your example of #14, I'm now using CreateBuffer(Data** ppData, unsigned char* pBuffer, int* pPointer, unsigned int size) and
Free(Data* pData), neatly wrapped in VIs containing Call Library Nodes. CreateBuffer gives me **ppData, which provides me the 1D labview data wire; *pBuffer, whose only purpose is to go to Free for clean exit of the application; *pPointer, which is fed to the grabber routines (through the ScatterLock pipe -- see below) which need the address of the buffer.

The capture is triggered by running the CLN containing the grabbing routine; the image data is then available for labview processing on the wire created from ppData. I hope this clarifies why I need both the wire and the pointer separately. I'm actually able to reasonably branch the ppData wire without losing the pointer validity.

I'm aware of all the caveats mentioned into this long thread. But as long as I have some control of them, and ensure that they are taken care of on the target machine with a specific labview version, I'm fine. Specifically: whether there are copies of the buffer or not should be evidenced by "Show buffer allocations"; synchronization issues are indeed another problem, solved here either using the asynchronous call sequence of this routines (the grabbing routine returns only upon completion, the ppData wire runs through a sequence frame containing the grabbing routine), or via OVERLAPPED structures (CreateEvent, WaitForSimpleObject, ResetEvent in kernel.dll). The issue whether Array Subset works in place by resizing the pointer or not is not important here, I can live with the buffer preallocated with a fixed size. About Labview wanting to relocate the buffer, I have an additional monkey in the sleeve, which I didn't mention earlier: the framegrabber library includes a ScatterLock routine, which takes as argument the pointer of the buffer, and returns a proprietary handle. It is actually this undocumented handle which is the input of the grabber routine, The documented purpose of the ScatterLock routine is to tell the OS not to relocate or fragment the allocate array. How this is respected by LV I do not know, but once more, it seems to work. The questions of lifetime and robustness w.r.o. additions to the diagram stays, but for the moment I'm satisfied. The ultimate test for me at this stage is that the application works in the present setup. If I discover catches, or something worth to report about, I won't fail to continue the thread!

Thanks to the both of you for the help and the insights,
Enrico
0 Kudos
Message 25 of 25
(1,126 Views)