BryCoBat Posted June 15, 2005 Report Share Posted June 15, 2005 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);} Quote Link to comment
BryCoBat Posted June 15, 2005 Author Report Share Posted June 15, 2005 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. Quote Link to comment
BryCoBat Posted June 29, 2005 Author Report Share Posted June 29, 2005 Found a solution to the root problem, we're just gonna use the Datalogging & Supervisory Control to act as the server for our data. It does what we want it to do, and without all this ActiveX fuss. Quote Link to comment
i2dx Posted June 29, 2005 Report Share Posted June 29, 2005 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 ... Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.