LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Passing parameters to Labview DLL from VB.NET

That's because it is a LabVIEW project to create a DLL (not a C project file) so that you can communicate using it from a non-LabVIEW code.  ".lvproj" is a LabVIEW project file extension.  You don't really need it, I always like to create work using projects so it has become a habit to start with a project file.  If you decide to use & modify those vi in LabVIEW to create a DLL, the project file will come handy as I have also included a build-specification for a DLL.

 

-DP

--------------------------------------------------------

New Controls & Indicators made using vector graphics & animations? Click below for Pebbles UI


0 Kudos
Message 11 of 21
(2,337 Views)

See also same question (from the same poster, I assume) asked here: http://lavag.org/topic/16905-calling-labview-dll-from-vbnet/

0 Kudos
Message 12 of 21
(2,330 Views)

void __cdecl LCDColor(LVRefNum *VISAIN, uint16_t LCDColor2,

            TD1 *errorInNoError, LVRefNum *VISAOUT, char OutputString[], TD1 *errorOut,

            int32_t len);

 

LVRefnum is as already mentioned an (U)Int32 value. But it is with an asterix and therefor by reference and not by value so the VB keyword should be accordingly ByRef and NOT ByVal.

 

However, you should really forget to try to call THIS API from VB. The TD1 errorIn and errorOut look suspicioisly like LabVIEW error clusters. A LabVIEW error cluster is in principle a structure which is possible in VB but the internal LabVIEW string is only possible to be created, handled and managed by calling LabVIEW manager functions from within your VB code. While theoretically possible to do it is in fact more than a pain in the a** and I would never ever go through the trouble of even attempting to do it. One problem but by fat not the only one, is that the location of the LabVIEW manager functions can and does depend on the LabVIEW version the DLL was created with. Locating the correct LabVIEW runtime DLL is more than troublesome, as your VB code would need to know in which LabVIEW version the DLL was created in, locate it from the registry and link to it dynamically. When using Visual C this is normally all done automatically by the labviewv.lib file that you link with your C(++) project, but VB does not use lib files at all.

Rolf Kalbermatter
My Blog
0 Kudos
Message 13 of 21
(2,315 Views)

I like your concept to pass simple strings and integers. Unfortunately, it's still not quite clear to me. For example, in your  1. You're Opening VISA using LabVIEW VISA Open - and you're only passing a text string to tell it which comport to open (you can get this string name from MAX, but I believe you already have something in your list that looks correct). After Openning VISA How I call Labview DLL " passing a text string to tell it which comport to open"?


It would help me  a lot to see C project example calling LabVIEW DLL this way.

 

Thanks.  

0 Kudos
Message 14 of 21
(2,298 Views)

Rolf,

 

Since calling Labview DLL with VISA parameters appeared much more complicated that I expected, could it be done a different way? For example, in my DLL I have a parameter  COLOR. It is coming from VB as simple integer which LV DLL converts its own way to change LCD color. Now could be similar approach used for VISA parameter or that cluster ERROR variables? For example, instead passing real VISA type parameter, VB sends an integer 1, and the code inside DLL just makes a selection such as  if this number =1 then use  COM1, if this number =2 then use  COM2. Then it uses the selected variable in appropriate format in VISA session. In this case VB would deal with its own standard variables and Labiew would deal with its own data types.  

0 Kudos
Message 15 of 21
(2,296 Views)

Well, I'll give you an example using my workstation here.  I have COM4 on my computer for RS232 (a USB-to-RS232 dongle is connected to one of the USB ports). I can open that port using VISA_Open.vi in the following example C code (VB.NET would be similar, just needs different syntax):

 

void main (void)

{

int error;

int i=0;

char RxStr[32];

int Length=0;

int BytesRead=0;

 

error = VISA_Open("COM4", 0);  //Open VISA - once this call is made, the reference is kept in "VISA_ref.vi" which is a part of the DLL but not accessible by a calling application.

 

While ((error == 0) && i < 5)   //Doing it 5 times while continuing to check that there was no error. This logic is just for example - it will stop if there is error.

{

   error == VISA_Write("Hello World", 0);  //Writing a string "Hello World" out to COM4

   if (error == 0)

       error = VISA_Read(11, &RxStr, &Length, &BytesRead, 0);   //If no error previously, read back 11 bytes

   i++;

}

 

error = VISA_Close(0);  //Close VISA

}

 

Refer to attached VISA_C_DLL.h file for calls - this file is generated (along with a DLL) when you build the LabVIEW project that I had attached earlier.

 

In the above C example, I got "COM4" from NI MAX (image attached) on my computer. The above call opens a VISA reference and keeps it in the DLL, you don't have to send any references back and forth.

 

Untitled.png

 

Hope this clarifies...

-DP

--------------------------------------------------------

New Controls & Indicators made using vector graphics & animations? Click below for Pebbles UI


0 Kudos
Message 16 of 21
(2,291 Views)

@Alex723 wrote:

Rolf,

 

Since calling Labview DLL with VISA parameters appeared much more complicated that I expected, could it be done a different way? For example, in my DLL I have a parameter  COLOR. It is coming from VB as simple integer which LV DLL converts its own way to change LCD color. Now could be similar approach used for VISA parameter or that cluster ERROR variables? For example, instead passing real VISA type parameter, VB sends an integer 1, and the code inside DLL just makes a selection such as  if this number =1 then use  COM1, if this number =2 then use  COM2. Then it uses the selected variable in appropriate format in VISA session. In this case VB would deal with its own standard variables and Labiew would deal with its own data types.  


 

Your mixing here apples and pears in your discussion. The LCD color value is always an integer, Visual Basic or LabVIEW. The LabVIEW frontpanel uses an enum, but technically an enum is still always an integer. You could create enum like datatypes in VB too, so you can write RED instead of 0 in your VB code.

 

Enum color As UShort
    RED = 0
    GREEN = 1
    BLUE = 2
    WRITE = 3
End Enum

A VISA refnum is a LabVIEW private datatype. It can be passed to non LabVIEW programming languages and back as integer, but those languages have no way to use it themselves in anyway, other than storing it as integer and passing it to other LabVIEW functions that can operate on this.

 

Basically something like the included should work, except that the Define Prototype dialog is rather murky for the VISA_Read function. Either I'm not understanding that dialog correctly because of its abominal limited and bad documentation or the person who wrote that dialog messed up for good for output strings at least until LabVIEW 2011 (I didn't check in 2012 yet).

 

I would expect that I could configure the input length of the RxStr parameter to be BytesToRead and the output length of that parameter to be BytesRead, yet for some reasons those seem to be inversed. Also because of that it seems inpossible to set the BytesToRead to be passed by value, which should be definitely possible, if it is correctly only used for the input length of the string parameter. Something is definitely at least to much limited here in the implementation and absolutely unsatisfactorily documented in the LabVIEW help.

 

However if you won't need to return strings for your driver, you could still do the rest like in the attached example that I took the liberty to create from a modified version of the example posted by BTC_admin. The use of the LV2 style global buffer/Action engine/(semi)-intelligent global, while correct like this is IMHO to much of a limitation as it will not allow easily to scale suc a driver up for more than one device at the same time.

 

But the VISA_Read function in the attachement definitely can't be used like it is now, until someone from NI can explain to me the rather weird behaviour about how to setup the RxStr buffer for creating the DLL.

 


For some reasons I can't seem to append any files here, except the lvproj file for some strange reasons. I attached the archive to the relevant thread on Lava, where I still seem to be able to upload files.

Rolf Kalbermatter
My Blog
0 Kudos
Message 17 of 21
(2,279 Views)

Following your example I would ask few more questions.

1.  "the reference is kept in "VISA_ref.vi" which is a part of the DLL but not accessible by a calling application."

In case I need to communicate with several instruments in my Labview DLL, (if I understand it right) I have to run VISA_Open function for each instrument, for example  VISA_Open("COM4", 0);  VISA_Open("COM2", 0); VISA_Open("GPIB ADDR=11", 0). Then appropriate references will be created and used wthin DLL. Do I need to create "VISA_ref.vi for each reference or it could hold all of them. Is it  clear for a Labview programmer or VISA_ref.vi should be created certain way to accept reference variable from  VISA_Open function.

 

2. Are these references valid within one DLL only? If I have several DLLs, do I need have this VISA_Open, VISA_Close steps in each DLL even if the same instruments will be called? 

 

3.Now back to my initial DLL which has the passing parameter * VISAIN for VISA resource name.Should this DLL be redone to remove this passing reference variable since it's coming from VISA_Open result.

 

As I mentioned before, I am not going to build Labview DLLs for this project, but I am trying to understand all neccesary features and requrements for VB.NET > Labview DLL communications.  

 

Thanks again to everybody

0 Kudos
Message 18 of 21
(2,227 Views)

1) Yes you would have to create seperate VISA Ref.vi for each connection, or better yet create a more intellegent VISA Ref.vi that can store multiple refnums with open, lookup and close methods.

 

2) A VISA refnum is valid in the context it was created. For one this is the process calling the DLL if this is a LabVIEW process with the same version as what the DLL was compiled with. If the DLL runs in a non LabVIEW process and/or was compiled in a different LabVIEW version the VISA refnum will be created and managed in the LabVIEW runtime that matches the version used to create the LabVIEW DLL. So you could end up with several runtimes in a single process if you start to mix and match LabVIEW DLLs created in different LabVIEW versions. As long as you do the VISA Open, VISA Read, VISA Write and VISA Close for a particular VISA refnum all in the same DLL, you won't have troubles, but trying to pass VISA refnums (or any refnums in fact) between different LabVIEW DLLs is setting yourself up for a true disaster sooner or later.

Take a look at the modified library I posted in the Lava thread to see how this can be done.

 

 

3) LVRefNum *VISAIN passes the LabVIEW VISA refnum. This is not really a resource name but a resource refnum. That is sligtly different as the refnum contains internally both the resource name and the underlaying ViSession. Depending how you configure the Call Library Node parameter LabVIEW will pass the refnum (Adapt To Type), the resource name (String) or the underlaying ViSession (Integer).

And I would not remove that, but simply make sure that the DLL exports both a "Device Open" and "Device Close" function and whatever else Read and Write your device needs. Device Open receives a simple string, calls VISA Open and any other Initialization code and returns a VISA refnum, all the other functions receive and return a VISA refnum except Close which will just receive it.

Rolf Kalbermatter
My Blog
0 Kudos
Message 19 of 21
(2,223 Views)

I am trying to fnalize my options:

 

  1. I tell to Labview programmer that I can’t call this DLL as it is

void __cdecl LCDColor(LVRefNum *VISAIN, uint16_t LCDColor2,  TD1 *errorInNoError, LVRefNum *VISAOUT, char OutputString[], TD1 *errorOut, int32_t len);

 

 I need DLL to be changed the way, adding VISA functions and replacing refnum parameters with standard integer or string type  

 

void __cdecl VISA_Open(char ComName[], int32_t ErrorValIn);

int32_t __cdecl VISA_Close(int32_t ErrorValIn);

int32_t __cdecl VISA_Read(uint32_t BytesToRead, char RxStr[], int32_t len,

        uint32_t *BytesRead, int32_t ErrorValIn);

int32_t __cdecl VISA_Write(char TxStr[], int32_t ErrorValIn);

 

void __cdecl LCDColor(uint16_t LCDColor2,  int32_t ErrorValIn , int32_t ErrorValOut,...);

 

And LCDColor DLL should get resource name (COM port number or GPIB address) from appropriate VISA_Open result. Unfortunately, I don't know how but hopefully it will be clear to LabView developer. 

 

2. In your other approach it looks like you suggest to keep existing DLL prototype with refnum variable LCDColor(LVRefNum *VISAIN,…), however to add to DLL another function Device Open which “receives a simple string, calls VISA Open and any other Initialization code and returns a VISA refnum”, Here it's not clear to me the structure of this Device Open function: what string variable we should pass to Device Open, in what format the return VISA refnum comes back to VB. Would this returned VISA refnum be the right type of variable which could be used directly as a *VISAIN parameter in the call of LCDColor(LVRefNum *VISAIN,…   )

 

Thanks a lot

0 Kudos
Message 20 of 21
(2,201 Views)