11-30-2012 03:41 PM
Has anyone been able to run the example "Using ActiveX to Call a LabVIEW VI from Visual C++" with Microsoft Visual studio 2010? Below is the code i am compiling. The code compiles and builds but the console hangs for about a minute or two then displays ("LV must be running, exiting ...\n"). It seems if the c++ application can not create an instance with the LV application. Has anyone ran into this issue ?
// Acquire.cpp : This source code is an Automation client. It calls the
// LabVIEW 7.1's automation server.
#import "C:\Program Files\National Instruments\LabVIEW 2011\resource\labview.tlb"
#define VI_PATH "C:\\Documents and Settings\\trujilloaa\\My Documents\\Comm Example\\LabView Call\\var_test.vi"
#include "windows.h"
#include "stdio.h"
#include "conio.h"
#include <stdlib.h>
#include <string.h>
// Include the LabVIEW Automation Server Type Libraries
//#import LABVIEW_TLB_PATH
main()
{ // declare variant data structures
// _variant_t is a class wrapper for variant data types
_variant_t one_str;
_variant_t str_list;
int size = 0;
char Path[1000],Password[60] = "";
// a SAFEARRAY is used to access the data from an array
SAFEARRAY *psa = NULL;
char VIPath[100] = "C:\\Documents and Settings\\trujilloaa\\My Documents\\Comm Example\\LabView Call\\var_test.vi" ;
// generate a namespace declaration to and identify and assign a name to a declarative region.
// In this case we are assigning the LabVIEW.
using namespace LabVIEW;
_ApplicationPtr pLV;
VirtualInstrumentPtr pVI;
CoInitialize(NULL);
// Create Reference to LabVIEW ActiveX COM object
pLV.CreateInstance("LabVIEW.Application");
if (pLV == NULL)
{ printf("LV must be running, exiting ...\n");
return false;
//break;
}
// Create Reference to VI
pVI.CreateInstance("LabVIEW.VirtualInstrument");
//strcpy(Path, pLV->ApplicationDirectory);
strcpy(Path, VIPath);
// assign an object reference to the pVI.
pVI = pLV->GetVIReference(LPCTSTR(Path), LPCTSTR(Password), 0,0x01);
// configure the VI to show its front panel on Call.
pVI->ShowFPOnCall = TRUE;
// set the values for the controls of the VI
pVI->SetControlValue("StrIn0", "String 1");
pVI->SetControlValue("StrIn1", "String 2");
pVI->SetControlValue("StrIn2", "String 3");
//Transfer control to LabVIEW with the Run statement. The call function passes the parameter names
// and data to the LabVIEW VI.
pVI->Run(0);
// Get the values from the indicators. GetControlValue returns a _variant_t
// type. Here we explicitly assign our string values as _bstr_t.
one_str = pVI->GetControlValue(_bstr_t("StrOut"));
str_list = pVI->GetControlValue(_bstr_t("LstStrOut"));
// We can use V_VT(&_variant_t) to test the type of our variant. The variant
// data structure stores several different type values and an attribute
// for which type this variant should be converted to.
if (V_VT(&one_str) == (VT_BSTR))
{ printf("One String is a bstring\n"); }
// assign our SAFEARRAY to the array type of the variant
if (V_VT(&str_list) == ( VT_ARRAY | VT_BSTR ))
{ printf("This is an array of bstrings\n");
psa = V_ARRAY(&str_list);
}
HRESULT hr;
LONG cElements, lLBound, lUBound;
BSTR HUGEP *pbstr;
// Get the number of dimensions of our array
printf("Number of channels: %d\n",SafeArrayGetDim(psa));
// Get the lower bound
hr = SafeArrayGetLBound(psa, 1, &lLBound);
if (FAILED(hr)) return false;
//Get upper bound
hr = SafeArrayGetUBound(psa, 1, &lUBound);
if (FAILED(hr)) return false;
//Get total number of elements
cElements = lUBound-lLBound+1;
// Use SafeArrayAccessData to place a lock on the data so that we
// can access the data in our application
hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pbstr);
if (FAILED(hr))return false;
// Iterate through the array and print the values
for (int i = 0; i < cElements; i++)
{ _bstr_t mybstr(pbstr[i]);
printf("Data:<%s>\n",(char*)mybstr);
}
// Unlock the data
SafeArrayUnaccessData(psa);
// make sure the output is flushed to the screen
fflush( stdin );
while(!kbhit());
return (0);
}
12-03-2012 05:37 PM
Hi antz24,
Which version of LabVIEW are you using? This example was developed and verified for Visual c++ 6.0 and LabVIEW 7.1. If you are using a different version of LabVIEW, it is likely that the ActiveX methods have changed. Below are the ActiveX methods for LabVIEW 2012:
http://zone.ni.com/reference/en-XX/help/371361J-01/axprop/vi_class_method/
Here is some documentation on calling LabVIEW VIs using different programming languages.
http://www.ni.com/white-paper/5719/en#toc1
Also, what exactly is it that you are trying to do? In most cases, your application would probably be best served if it interfaced with your LabVIEW VI as a DLL.
12-03-2012 06:20 PM
The version i am currently using is LabVIEW 2011. We have used a DLL in the past but that will not work for this particular issue. We need to pass a FPGA board handle through our software in order to rd and wr registers. Currently we have a dll which simply opens and closes the board everytime we wanted to rd or wr. We found out the there is a memory leak in the board devlopers API and since we read and write mulitple times we need to just open and close the board once during the entire Labview session . Active X we felt was the best option . I am hoping i can pass data from Labview to C++ while having a application in the background that keeps the global handle open for reading and writing regs .The call to create a Application object should be CreateInstance("Labview.Application") correct? The code i have currently does not even create an application object. What occurs is it starts Labview and then errors out. I dont know if it is a coding issue or a permissions issue.
12-04-2012 06:29 PM
Hi antz24,
I believe you are correct in how you are creating your application object. As of right now I am unsure on whether your error is resulting from your LabVIEW 2011 interfacing with what may be out-of-date ActiveX calls or not, I'm still looking into examples of using ActiveX as a server with LabVIEW 2011. What type of C++ are you programming with?
02-18-2013 05:41 AM