LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to pass a struct to a DLL function and accessing it in another VI

Hi friends,
                   I am new to labview. I need to create a demo program in labview ,for displaying image from our own image capturing system. We have a  DLL ( build in VC++) containing functions for capturing image from our system. Now I need to create a VI library for some of functions in DLL and Create a Demo program using those created subvi library . I used "Call Function node" and created some of subvi's.

 Some of our DLL functions need to pass struct pointers.  Our function prototype will be similar to the following function.

__declspec(dllexport) int __stdcall Initialize( unsigned char *imagebuffer,struct config *Configuration);

The passed struct is similar to
struct config
{

  double                val1[3];
  unsigned short   val2;
  bool                    val3;
  bool                    val4[3];    

  unsigned char    val5;    
  unsigned char   val6[3];
  bool                    val7[26];

 };

For passing "unsigned char *imagebuffer"  I initialized array with "Numeric constant " and set the size of the array and send to the function.
The problem here is, I used this array in one of the subvi. 
How can I use the returned imagebuffer array  in my main demo program. How to connect the image array to subvi "Connecter Pane"
And  which control  can I use to display the image. The image data I get is form of 1-D Array .


The second problem is,
                             For passing the structure,  I used "Bundle " and filled the bundle with all the datatypes as in my struct and passed to the function. Is it correct ?  How to access this bundle after returned from function  in another Vi. ie.) How to connect this bundle to the connter pane ?


Thanks for your valuable suggestions.

aajjf.

Message Edited by aajjf on 04-19-2007 05:34 AM

0 Kudos
Message 1 of 7
(3,873 Views)

Hi,

I'm not sure if I understand you correctly. It sounds like you want to pass the image array from your subvi to your main vi. If this assumption is correct, then you've got a simple fix:

First, in your subvi, make sure that the image array is displayed as an indicator on your front panel (the format of this display doesn't matter). Locate the vi icon in the top right corner of your window, right-click on it and select Show Connector. The icon now has changed to block of rectangles. When you hover over it, the cursor morphs into the wire spool; click on one of the rectangles and then click on the image array indicator. Now this subvi has a terminal that will pass the image array to the main vi that you place it in. Save the subvi, place it in your main vi and you'll see that it now has a wire which you can connect to and retireve the array. You'll do the same for your cluster of bundled data types.

Let me know if I've misunderstood. I'd like to be of help.

Cheers,

Emilie Kopp | Applications Engineer | National Instruments

0 Kudos
Message 2 of 7
(3,845 Views)


@aajjf wrote:
Hi friends,
                   I am new to labview. I need to create a demo program in labview ,for displaying image from our own image capturing system. We have a  DLL ( build in VC++) containing functions for capturing image from our system. Now I need to create a VI library for some of functions in DLL and Create a Demo program using those created subvi library . I used "Call Function node" and created some of subvi's.

 Some of our DLL functions need to pass struct pointers.  Our function prototype will be similar to the following function.

__declspec(dllexport) int __stdcall Initialize( unsigned char *imagebuffer,struct config *Configuration);

The passed struct is similar to
struct config
{

  double                val1[3];
  unsigned short   val2;
  bool                    val3;
  bool                    val4[3];    

  unsigned char    val5;    
  unsigned char   val6[3];
  bool                    val7[26];

 };

For passing "unsigned char *imagebuffer"  I initialized array with "Numeric constant " and set the size of the array and send to the function.
The problem here is, I used this array in one of the subvi. 
How can I use the returned imagebuffer array  in my main demo program. How to connect the image array to subvi "Connecter Pane"
And  which control  can I use to display the image. The image data I get is form of 1-D Array .


The second problem is,
                             For passing the structure,  I used "Bundle " and filled the bundle with all the datatypes as in my struct and passed to the function. Is it correct ?  How to access this bundle after returned from function  in another Vi. ie.) How to connect this bundle to the connter pane ?


Thanks for your valuable suggestions.

aajjf.

Message Edited by aajjf on 04-19-2007 05:34 AM


You say nothing about how your cluster looks but I'm afraid you did the standard error here and placed arrays in it. That is not what the C structure is representing for several reasons.

First fixed size arrays in C are inlined inside a structure, so are not a pointer but for the case of your val1 element three doubles.

Second although not relevant here because of above point: LabVIEW arrays are not the same as C arrays. LabVIEW uses a pointer to a pointer and has the size of the array in elements prepended to the array data. C simply uses a pointer and all the rest is the programmers sorrow. The Call Library Node does convert the top level element of variables you pass according to the type configuration of that parameter but does no conversion of internal elements at all. So passing clusters with anything like arrays or strings is always wrong unless the DLL is aware of the specific datatypes LabVIEW uses.

Last but not least you can end up with alignment issues. Elements in structures are aligned by every C compiler to a certain value. This value can be defined by the programmer in the project settings or for Visual C through #pragma pack() statements in the C code. The alignment rule says that an variable is aligned to the smaller of the two values that are either a multiple of the variable element size or the alignment setting. Most 32bit code nowadays uses 8 bit default alignment but LabVIEW always uses 1 byte. In your case there is nothing to observe since the large variables are at the beginning. Otherwise you might have had to insert filler elements in the LabVIEW cluster.

One last thing bool is a C++ type only. Its size is 1 byte and incidentially this is the same LabVIEW uses for Booleans.

Rolf Kalbermatter

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 3 of 7
(3,840 Views)
Hi friend thanks for your replies.


Since I felt difficult with the structures, I created a wrapper Function in my DLL , without using sturct. So my second problem is solved.

Hi Emilie Kopp,
                         Thanks for the suggestions. I have a problem in displaying the 1D array image data. I have attached my part of code that displays the data .Have a glance and inform me incase of any error I have made. Or suggest any other method to display the image. I will display 30 frames in a second.

My imageCapture() declaration is  :   "
__declspec(dllexport) int __stdcall ImageCapture(unsigned char *DisplayBuffer);"          

In " Call Library Function node" I have initialized as  follows :
 
Function Name :  
           ImageCapture            "Run In UI Thread "

Calling Conversion : 
     stdcall(WINAPI)

   Parameter         :                 Type :                                    DataType:

ReturnStatus                    Numeric                                      Signed 16-Bit Integer

DisplayBuffer                   Array                                              unsigned 8-Bit Interger.




My function is shown in Function prototype window as :  " short int ImageCapture(unsigned char *DisplayBuffer);"




Am I making any mistakes ? 

Thanks for the help.


AAJJF.

0 Kudos
Message 4 of 7
(3,824 Views)


@aajjf wrote:
Hi friend thanks for your replies.


Since I felt difficult with the structures, I created a wrapper Function in my DLL , without using sturct. So my second problem is solved.

Hi Emilie Kopp,
                         Thanks for the suggestions. I have a problem in displaying the 1D array image data. I have attached my part of code that displays the data .Have a glance and inform me incase of any error I have made. Or suggest any other method to display the image. I will display 30 frames in a second.

My imageCapture() declaration is  :   "
__declspec(dllexport) int __stdcall ImageCapture(unsigned char *DisplayBuffer);"          

In " Call Library Function node" I have initialized as  follows :
 
Function Name :  
           ImageCapture            "Run In UI Thread "

Calling Conversion : 
     stdcall(WINAPI)

   Parameter         :                 Type :                                    DataType:

ReturnStatus                    Numeric                                      Signed 16-Bit Integer

DisplayBuffer                   Array                                              unsigned 8-Bit Interger.




My function is shown in Function prototype window as :  " short int ImageCapture(unsigned char *DisplayBuffer);"




Am I making any mistakes ? 

Thanks for the help.


AAJJF.



You can display it as an array of bytes. That is fast. If you want to see the image itself you will have to convert it either into a Picture Control or an IMAQ Vision picture. The first will never be able to give you 30 fps and the second is not free.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 5 of 7
(3,815 Views)
Hi Rolf Kalbermatter , thanks for your reply.
 

Can you suggest me , how to display the array of bytes ?  which control should I use? 

As I have given in the block diagram code, I used Reshape array to convert 1 D array to 2D array , pass the 2Darray to the Draw Flattent Pixmap, and then pass the picture to the picture control.   Is this correct method ?  or is there any other method to do it.

In the current method, the Reshape Array always gives data of "0".

0 Kudos
Message 6 of 7
(3,808 Views)


@aajjf wrote:
Hi Rolf Kalbermatter , thanks for your reply.
 

Can you suggest me , how to display the array of bytes ?  which control should I use? 

As I have given in the block diagram code, I used Reshape array to convert 1 D array to 2D array , pass the 2Darray to the Draw Flattent Pixmap, and then pass the picture to the picture control.   Is this correct method ?  or is there any other method to do it.

In the current method, the Reshape Array always gives data of "0".


It all depends on the format of your bitmap in the byte array.  What I meant with displaying is just a simple array control shell with an uInt8 integer inside.

Your idea to use the Flatten Pixmap function and display it in a Picture Control goes in the right direction. But it will most probably be quite some work before that is successful. Bitmaps can and are in a miriad of possible formats. Things like width and height, number of bits per pixel, pixel color format, row alignment, color lookup table for low color images etc, can vary greatly and have a direct influence of how the bits are formated into the image data stream and what their specific meaning is.

The most direct approach would be to feed your 1D array directly into Draw Flattened Pixmap.vi. This VI has certain very specific ideas about how the 1D array of bytes is formatted and if you do not get the image as it should be from this VI, you will have to dive into lowel level bitmap stuff. Possible solutions are to either reformat the data stream on the C side into one that the Pixmap to Picture Control VI does understand or to create your own Draw Flattened Pixmap.vi, that does understand the formatting of your data stream. There is nothing else to this. Bitmaps can be in many varied formats and LabVIEW has no way of guessing how your 1D array would be formatted in. Also because of those different formats there is no standard that is just right. Every format is right for the specific use it was designed for even if that format was sometimes only chosen to be different than anyone else.

Reshape array needs the actual witdth and height of the 2D array you want to create. If you leave it open it will assume 0 and create an array of 0 * 0 elements independant of how many bytes you feed it with.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 7 of 7
(3,803 Views)