LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

OPC variant from GetOPCServers()

Hello all,
  I'm trying to get a list of OPC servers on my local computer through an OPC automation dll.  I first used NI's create ActiveX controller wizard to setup the wrapper .fp instrument.  When I call GetOPCServers() in my .fp, the return value is zero and the variant * is displayed in the variable window with the value {VT_BSTR | VT_ARRAY}.  Theoretically, the return value should contain an array of strings, so perhaps this is appropriate, and the return value indicates no failure.
 
  But as I try to dig the value out of the variant, CA_VariantGetType() return 0x1073--which must be incorrect.  The function CA_VariantGetArrayNumDims() indicates that 1 dimension is present, but CA_VariantGet1DArraySize() indicates the size of the array dimension is zero.  Is that function even appropriate?  Trying to retrieve a CSting or BSTR out of the array either returns an error or returns garbage.  Is anyone familiar with this stuff?
 
Thanx,
Orlan
0 Kudos
Message 1 of 5
(4,845 Views)

Here is one way to deal with variants containing strings:

#include <ansi_c.h>
#include <cviauto.h>

void main(void)
{
 VARIANT      vt;
 char         *inputArray[] = { "1", "23", "456" }, **outputArray = 0;
 unsigned int vtType, numElems, numDims, i;
 
 CA_VariantSet1DArray(&vt, CAVT_CSTRING, sizeof(inputArray)/sizeof(*inputArray), inputArray);
 vtType = CA_VariantGetType(&vt);
 CA_VariantGetArrayNumDims(&vt, &numDims);
 CA_VariantGet1DArraySize(&vt, &numElems);
 printf("Variant type: 0x%x, dimensions: %d, number of elements: %d\n", vtType, numDims, numElems);
 
 if (vtType == (CAVT_CSTRING | CAVT_ARRAY))
 {
  CA_VariantGet1DArray(&vt, CAVT_CSTRING, &outputArray, &numElems);
  for (i = 0; i < numElems; ++i)
  {
   printf("array[%d] = %s\n", i, outputArray[i]);
   CA_FreeMemory(outputArray[i]);
  }
  CA_FreeMemory(outputArray);
 }
 
 CA_VariantClear(&vt);
 getchar();
}

Message 2 of 5
(4,815 Views)

Hi Mohan,

  I got everything to work with your help!  The solution actually involved two separate parts.  First, I got sloppy and forgot to initialize my char ** before passing it to CA_VariantGet1DArray().  Your sample code reminded me of this.  No error code was ever returned (which is odd), but the array of strings was junk because the variant safearray from GetOPCServers() was junk, so who cares?  Now to the other part of the solution.

  In preparation for CVI 8, I completely uninstalled all NI software last night.  I reloaded everything and then let CVI 8 regenerate the OPC automation wrapper.  Suddenly, CA_VariantGet1DArraySize() started returning 7 elements--which is now the number of registered OPC servers on my computer.  My CVI 7.1.1 install was reporting 0 elements from the same variant (at the time it should have been 5).  So the big questions is: does CVI 8 have new ActiveX library\controller wizard code that was not in CVI 7.1.1 and this fixed the problem of a corrupt variant, or was it that a fresh reload of CVI 7.1.1 would have also caused the number of elements to be reported correctly?  I would definitely like to hear an answer from NI on this.

/* begin whining */  My previous post indicated that the variables debug window and CA_VariantGetType() did not agree precisely on the variant data type.  It still doesn't with CVI 8.  Obviously, the variables window doesn't use the same code that CA_VariantGetType() does when it displays the variant value--which is also odd.  If the variable window is more correct, then CA_VariantGetType() should have returned 0x106C instead of 0x1073.  If CA_VariantGetType() is more correct, then the variable window should have indicated {CAVT_CSTRING | CAVT_ARRAY} instead of {CAVT_BSTR | CAVT_ARRAY}.  It does change the CVI code to handle the BSTR, even though you can eventually arrive at the same char ** result.  It just seems a bit sloppy to me.  /* end whining */

As far as NI knows, is BSTR/CSTRING the only automation type pair that will involve a disagreement between the two sources?  I would also like an answer from NI on this, please.

Orlan

0 Kudos
Message 3 of 5
(4,786 Views)

Hello cosmo

I cannot really say for sure why GetOPCServers() starting working for you. If you have something I could install here to investigate this further, I can try and find out some more. But at this point, I am not sure what might have caused this.

Regarding the variable window, the window uses a different code path from the CVI ActiveX library. The ActiveX library simplifies certain activex types to make them more compatible with C types. The variable window on the other hand displays data the way it is and hence showed the BSTRs instead of CStrings in your case. An example of simplifying the data types was to report BSTRs as CStrings, since a C user cant really do much with a BSTR with C string functions. Other variant types are passed through the CVI ActiveX API as is. Unless ofcourse they are activex object handles or IDispatch pointer, in which case the CVi ActiveX library handles them internally.

I hope this helps
Bilal Durrani
NI
0 Kudos
Message 4 of 5
(4,745 Views)

Hey Bilal,

  That explanation sounds good enough for me.  I simply need to understand it as much as possible so that I don't do unnecessary coding.  Also, I don't want to make stupid programming mistakes unnecessarily just because I don't understand the main concepts with a technology that is useful.  Thanx again guys!

Orlan

0 Kudos
Message 5 of 5
(4,739 Views)