Jump to content

Trouble reading array from LV 7.1 ActiveX w/ VC++6


Recommended Posts

Using LabVIEW 7.1 and VC++ 6.0.

I'm having trouble reading data out of an array indicator via ActiveX. I've tried just running the VI, and building it to an .exe, and I'm using a little C++ app (modified from the example code in Calling_LabVIEW_from_C++_Using_ActiveX for now, the real project is something a bit bigger than that) to read the value. I can read scalars just fine using the following code (with appropriate changes). However, the array comes back with the proper type for an array of strings (VT_ARRAY | VT_BSTR), and I get the right dimensions back from SafeArrayGetLBound and SafeArrayGetUBound, but all the elements just point to 0xCCCCCCCC. Is there some extra encoding going on between the LabVIEW array and the ActiveX SafeArray?

The app code (tabs have been eaten by the forum monster):

#include "stdafx.h"#include "windows.h"#include "stdio.h"#include "conio.h"#include <stdlib.h>#include <string.h>#include <iostream.h>#include <comutil.h>#import "LabVIEW.tlb"#define VIPATH "C:\\LabVIEW\\MyApp\\DIAG\\AI Diagnostics.vi"using namespace MyApp;int main(int argc, char* argv[]){VARIANT sample;int size = 0;char Path[1000],Password[60] = "";// generate a namespace declaration to and identify and assign a name to a declarative region.// In this case we are assigning the LabVIEW._ApplicationPtr pLV;VirtualInstrumentPtr pVI;cout << "Pre-CoInitialize" << endl;CoInitialize(NULL);do{VariantInit(&sample);cout << "Initialized, creating MyApp.Application instance" << endl;pLV.CreateInstance("MyApp.Application");if (pLV == NULL){printf("LV must be running, exiting ...\n");break;}cout << "Obtained App instance, creating VI instance" << endl;pVI.CreateInstance("MyApp.VirtualInstrument");cout << "Got VI instance" << endl;strcpy(Path, VIPATH);// assign an object reference to the pVI.VARIANT_BOOL resvForCall = TRUE;long options = 0x0;cout << "Getting Ref to Desired VI" << endl;pVI = pLV->GetVIReference(LPCTSTR(Path), LPCTSTR(Password), resvForCall, options);// configure the VI to show its front panel on Call.pVI->ShowFPOnCall = TRUE;sample.vt = VT_ARRAY;// Multiple reads to ensure that we don't get the default 0...sample = pVI->GetControlValue("Count Data");sample = pVI->GetControlValue("Count Data");// Check dimensions (comes back as 1)long cdim;cdim = SafeArrayGetDim(sample.parray);cout << "cdim = " << cdim << endl;// Check variant type, should be VT_ARRAY | VT_BSTRcout << "VT: " << sample.vt << endl;cout << "VT_ARRAY | VT_BSTR: " << (VT_ARRAY | VT_BSTR) << endl;// Check bounds before iterating over array to print valuesHRESULT he;bool goahead = true;long lbound;long ubound;he = SafeArrayGetLBound(sample.parray, 1, &lbound);if (FAILED(he)) {cout << "Failed getting lower bound." << endl;cout << "Bad Index? " << (DISP_E_BADINDEX == he) << endl;goahead = false;}he = SafeArrayGetUBound(sample.parray, 1, &ubound);if (FAILED(he)) {cout << "Failed getting upper bound." << endl;cout << "Bad Index? " << (DISP_E_BADINDEX == he) << endl;goahead = false;}cout << "Lower Bound: " << lbound << endl;cout << "Upper Bound: " << ubound << endl;// Print each elementif (goahead) {for (long i = lbound; i < ubound; i++) {VARIANT val;VariantInit(&val);val.vt = VT_BSTR;SafeArrayGetElement(sample.parray, &i, &val);cout << "Element VT: " << val.vt << endl;wprintf(L"(%d) The sample Value is %s\n", i, val.bstrVal);VariantClear(&val);}}// Wait to quitwhile( !kbhit() ) {cout << "Hit any key to continue\r";fflush( stdin );}pLV->AutomaticClose=0;VariantClear(&sample);} while (0);CoUninitialize();return (0);}

Link to comment

Made a little progress. I'm getting an E_INVALIDARG from SafeArrayGetElement, whether my last argument is a _bstr_t, BSTR, char* or VARIANT. The question is: what is the proper last argument? SafeArrayGetElement just says it's void* pvData, which...is just about useless (hooray for systems hungarian notation), and I guess the actual definition of the function is in a .dll somewhere, 'cause it's sure not in any .cpp files on my hard drive.

Link to comment
  • 2 weeks later...

it's always difficult to read data from the labview application into a C/C++ routine, because the LV datatypes are somewhat special ;) . my approach is - when i am not able to avoid this - to call a C++ routine via a call library node in labview which writes the data to the c++ application ... which has the advantage that i don't have to deal with the LV memory management ...

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.