LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Can LabVIEW make use of an OCX (ActiveX) "Pointer to Array"?

Hi,

I have an OCX library that is used to read images from a camera. After acquiring the data it can return either a variant associated with the data or a pointer to the 1D/U16 data array. If I use the variant and process the data flow through "Variant to Data" followed by a reshaping of the 1D-array to the appropriate 2D-array I can then display the image in an intensity graph. The problem I have with doing it this way is that the "Variant to Data" step takes an inordinately long time compared to everything else (76% or 840ms of the total time spent acquiring & displaying the image).

Is there a way for me to force a union of the array space associated with the intensity graph to the array space pointed to by the pointer to the 1D/U16 data array that I can also get from the OCX library?
0 Kudos
Message 1 of 32
(6,410 Views)
The way I understand the outputs of your ActiveX Invoke Node, you have optionally a Variant output, or a pointer to an array. While there is no way to create a union of memory spaces in LabVIEW, you should be able to wire the array output of the Invoke Node to any terminal that accepts an array input.

Would it be possible for you to post a screen shot of your Invoke Node so that I can have a clear idea of the output you are working with.

Scott Y
NI
0 Kudos
Message 2 of 32
(6,374 Views)
Attached you should find the screen shot.

The "LockForRead" terminal will NOT tolerate being directly connected to either the Reshape Array function or directly to the Intensity Graph indicator.

If I instead select the "LockForReadPtr" then I get an integer number.
0 Kudos
Message 3 of 32
(6,371 Views)
I was not able to find the LockForReadPtr on your screen shot. I think that method is not shown on your block diagram. Is it possible for you to post a link to a programming reference for this particular OCX library? With this documentation, or the name of the device you are communicating with, it will be easier to determine the proper way to use the returned value in LabVIEW.

Scott Y.
NI
0 Kudos
Message 4 of 32
(6,349 Views)
You are right, "LockForReadPtr" is NOT on the screen because I don't know of any way to use a "pointer to array" within LabVIEW. I can send you a screen shot with the LockForReadPtr method visible, but what do you propose I hook it up to that would be useful? It's just a single I32 value.

The document you are asking for is here:

"iPORT PT1000 Visual Basic SDK Reference Guide.pdf"
http://www.pleora.net/customer/documentation/iPORT%20PT1000%20Visual%20Basic%20SDK%20Reference%20Guide.pdf

It's a bit over 3 Mbytes and I think you'll need to request a password from Pleora to access this portion of their site (just a formality with them).

There's also a 6+ Mb version for C++ there that contains similar information.

I've edited out the descriptions of the functions and attached that little bit to this message.

Message Edited by Warren Massey on 03-11-2005 12:45 PM

Message Edited by Warren Massey on 03-11-2005 12:47 PM

0 Kudos
Message 5 of 32
(6,347 Views)
FWIW, I have tried putting together a simple DLL which will take:
1) a pointer to an I16 array #1
2) the length of array #1
3) an I16 array #2
and it will move all the values from array #1 to array #2.
That is it will do it if the #1 array is also a LabVIEW array
(I get its pointer with another call to another simple routine in the DLL).

Unfortunately it won't work if I use the array pointer I get from the "LockForReadPtr" method. When the CIN executes, I get a message about something nasty having happened within the DLL and LabVIEW will be crashing as soon as I say it's OK to do so.

I'm running out of ideas...
0 Kudos
Message 6 of 32
(6,326 Views)
As I understand it, using the variant works but is too slow. Variants do have overhead. Here is a possible way to get faster performance, but it is more work:

Create a DLL that takes as a parameter a LabVIEW array which you pass into the DLL from the block diagram via the Call Library function.

In the DLL:
1. Call LockForReadPtr.
2. Figure out the size of the data at the pointer that LockForReadPtr returns.
3. Resize the LabVIEW array so that it is large enough to hold that data, using the LabVIEW memory manager functions (e.g. NumericArrayResize). These are explained in the "Using External Code in LabVIEW" manual.
4. Copy the data into the LabVIEW array.

Step 3 is actually only necessary if you don't know the size of the returned image in advance. If you do know, then you can pass a constant LabVIEW array of sufficient size from the block diagram, and avoid resizing it in the DLL. This is highly preferable!

Following these steps, you should be able to use the array that comes out of the right hand side of the Call Library function.

Steven H.
0 Kudos
Message 7 of 32
(6,323 Views)

Message Edited by Warren Massey on 03-12-2005 03:52 PM

0 Kudos
Message 8 of 32
(6,315 Views)

@steven H. wrote:
As I understand it, using the variant works but is too slow. Variants do have overhead. Here is a possible way to get faster performance, but it is more work:

Create a DLL that takes as a parameter a LabVIEW array which you pass into the DLL from the block diagram via the Call Library function.

In the DLL:
1. Call LockForReadPtr.
2. Figure out the size of the data at the pointer that LockForReadPtr returns.
3. Resize the LabVIEW array so that it is large enough to hold that data, using the LabVIEW memory manager functions (e.g. NumericArrayResize). These are explained in the "Using External Code in LabVIEW" manual.
4. Copy the data into the LabVIEW array.

Step 3 is actually only necessary if you don't know the size of the returned image in advance. If you do know, then you can pass a constant LabVIEW array of sufficient size from the block diagram, and avoid resizing it in the DLL. This is highly preferable!

Following these steps, you should be able to use the array that comes out of the right hand side of the Call Library function.

Steven H.




I'm not sure I would even know how to begin to call the LockForReadPtr method WITHIN the DLL!

How is this different than that which I just tried that didn't work? Admittedly I called the LockForReadPtr within LabVIEW and passed the pointer value it returned on into the DLL which was supposed to do the movement and there the process broke down.

Take a look in the attached zip file at the screen shots to see what I have tried doing. The more complex screenshot (LockForReadPtr.jpg) is what I'd like to get working but which does not work at this time (it crashes LabVIEW). The Test_MoveImage_DLL.jpg screenshot uses the exact same DLL and it does work properly. In the 1st case (that crashes) the array comes from the OCX code, in the second case (that works) the array comes from within LabVIEW. I don't know what would be different between the arrays within the Windows environment but obviously there is something. I've also include in the ZIP file the C++ code that went into the DLL.

... and this is what LabVIEW thinks the interface to the DLL consists of:
long MoveImage(unsigned long ImagePointer, unsigned short int DisplayArray[], long ImageSize)


Any other suggestions? I've about reached my hrair limit in dealing with this...
0 Kudos
Message 9 of 32
(6,316 Views)
I looked at the screenshots. I understand what you're trying and why it's not clear what the difference is.

The likely reason that the approach shown in LockForReadPtr.jpg does not work is that the ActiveX server you are calling is running in a separate process from that of LabVIEW and the DLL you built. A pointer in one process can't be used in another process.

The approach shown in Test MoveImage DLL.jpg does work because LabVIEW and the DLL are in the same process. However, I would not rely on this method; the "pointer" passed out of the first DLL call might become stale if LabVIEW decides to do some memory cleanup/rearrangement. (I realize you did this just as an experiment; I make the comment more in a general sense.)

Is there any example code available from the vendor that shows how this ActiveX server would be called from Visual Basic, C, or C++? I might have more insight if I could see that.

Steven H.
0 Kudos
Message 10 of 32
(6,307 Views)