ni.com is currently experiencing unexpected issues.
Some services may be unavailable at this time.
08-19-2010 06:14 AM
That worked great.
Can you tell me how do I create the required Variant. Should I create the Parameters array as array of variants or should I create the element returned alone as variant ?
08-24-2010 10:45 AM - edited 08-24-2010 10:52 AM
Hi Sathish,
phew, that was quite hard. You have to create a VARIANT with a VT_ARRAY | VT_VARIANT | VT_BYREF type
containing VT_BYREF VARIANTs. I have added two indicators to your original VI, an integer "Write" and an array "DataOut". Here is a Python script that works so far. Looks a little bit weird, I admit
###
DataOut = VirtualInstrument.GetControlValue("DataOut")
from ctypes import *
import numpy
import comtypes.client
from comtypes.automation import VARIANT
from comtypes.automation import VT_ARRAY
from comtypes.automation import VT_BYREF
from comtypes.automation import VT_R8
from comtypes.automation import VT_I4
from comtypes.automation import VT_VARIANT
from comtypes.automation import _midlSAFEARRAY
comtypes.CoInitialize()
# Path to type library.
TypeLibPath = "C:/Program Files/National Instruments/LabVIEW 8.6/resource/labview.tlb"
# Attention: For unknown reason first attempt of type library import via
# GetModule() fails if comtypes.client.gen_dir is set to a directory.
# Solution: Set it to none so all imported data is kept only in memory.
comtypes.client.gen_dir = None
comtypes.client.GetModule(TypeLibPath)
# Create a VARIANT with VT_BYREF flag. The union of VARIANT values in comtypes class tagVARIANT
# isn't complete, most pointer members are missing. That isn't a problem, however: Since all pointers
# in a union have the same address we only need one of them. Fortunately, there's a member
# c_void_p available for general purpose pointer access. Idea from comtypes-users mailing list
# http://www.mail-archive.com/comtypes-users@lists.sourceforge.net/msg00530.html
def VARIANT_VT_BYREF(obj, vartype):
var = VARIANT()
# Pointer assignment: addressof(obj) returns the pointer to obj.
# obj has to be a ctypes object, otherwise addressof() makes no sense and fails!
var._.c_void_p = addressof(obj)
var.vt = vartype | VT_BYREF
return var
try:
Application = comtypes.client.CreateObject("LabVIEW.Application.8", None, None, comtypes.gen.LabVIEW._Application)
# Parameters
Channel_1 = [1, 2, 3]
Channel_2 = [4, 5, 6]
ArrayData = numpy.array([Channel_1, Channel_2], numpy.double)
# comtypes 0.6.2: It seems that VARIANT does not support numpy arrays yet,
# but _midlSAFEARRAY does. Thus we have to create a _midlSAFEARRAY object
# and wrap it in a VARIANT manually.
Data = VARIANT()
# Taken from file safearray.py, class tagVARIANT, method _set_value()
SafeArray = _midlSAFEARRAY(c_double).create(ArrayData)
memmove(byref(Data._), byref(SafeArray), sizeof(SafeArray))
Data.vt = VT_ARRAY | SafeArray._vartype_
# Create VARIANT.
Read = VARIANT("TRUE")
# Create a ctypes int. We need a pointer to it later.
tempint = c_int(0)
# Create VARIANT to use as [out] parameter.
Write = VARIANT_VT_BYREF(tempint, VT_I4)
# Create SAFEARRAY for return values from dummy array.
SafeArrayOut = _midlSAFEARRAY(c_double).create([])
# Create VARIANT to use as [out] parameter.
DataOut = VARIANT_VT_BYREF(SafeArrayOut, VT_ARRAY | VT_R8)
Read = "TRUE"
ParameterNames = ("Data", "Read", "Write", "DataOut")
# Create SAFEARRAY.
ParametersArray = _midlSAFEARRAY(VARIANT).create([Data, Read, Write, DataOut])
# Create VARIANT to use as [in, out] parameter.
Parameters = VARIANT_VT_BYREF(ParametersArray, VT_ARRAY | VT_VARIANT)
VIPath="C:\zjmwi\SimpleData86.vi"
# Get VI Reference
VirtualInstrument = Application.GetVIReference(VIPath)
# Open VI front panel in hidden mode
VirtualInstrument.OpenFrontPanel(True,1)#3)
# Call VI
print ("Calling LabVIEW VI\n")
VirtualInstrument.Call(ParameterNames,Parameters)
print Parameters
except:
VirtualInstrument = None
Application = None
# rethrow the exception to get the full trace on the console
raise
VirtualInstrument = None
Application = None
###
But wait, there's a much simpler solution: Use the "Parameters" VARIANT only to pass control values to your VI, but not to return data from indicators. Instead, get your data after calling the VI via GetControlValue():
DataOut = VirtualInstrument.GetControlValue("DataOut")
candidus
08-07-2018 12:30 PM
Another approach is to use my company's product, TestScript, to communicate between LabVIEW and Python. We've abstracted out the TCP/IP communication between LabVIEW and Python, so you can just code. Python can control LabVIEW, and LabVIEW can execute Python scripts: control is fully bidirectional. TestScript is also free for download and source-released! Enjoy!
09-23-2019 04:26 AM - edited 09-23-2019 04:27 AM
Hi candidus,
I am trying to execute a VI file with cluster and 2D array data from python. I have used your code the one which does not include VARIANT is working for me partially, as in i am able to invoke LabVIEW, run the vi file and able to pass the input parameters from python to vi file. It doesn't execute though and also, it is running mode till I manually abort the execution. After which it throws error:
Calling LabVIEW VI
Traceback (most recent call last):
File "C:\dev\venv\lib\site-packages\comtypes\automation.py", line 775, in Invoke
byref(result), byref(excepinfo), byref(argerr))
_ctypes.COMError: (-2147352567, 'Exception occurred.', (None, None, None, 0, None))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "testvi.py", line 41, in <module>
VirtualInstrument.Call(ParameterNames,Parameters)
File "C:\dev\venv\lib\site-packages\comtypes\__init__.py", line 560, in func
return self.Invoke(obj, memid, _invkind=1, *args, **kw) # DISPATCH_METHOD
File "C:\dev\venv\lib\site-packages\comtypes\automation.py", line 782, in Invoke
raise COMError(hresult, text, details)
_ctypes.COMError: (-2147352567, 'Exception occurred.', ('LabVIEW : VI execution terminated by the server.', 'LabVIEW', None, 0, 0))
This code with variant is giving me GetModule error i.e.
Traceback (most recent call last):
File "testvi2.py", line 29, in <module>
comtypes.client.GetModule(type_libpath)
File "C:\dev\venv\lib\site-packages\comtypes\client\_generate.py", line 110, in GetModule
mod = _CreateWrapper(tlib, pathname)
File "C:\dev\venv\lib\site-packages\comtypes\client\_generate.py", line 180, in _CreateWrapper
exec(code, mod.__dict__)
File "<string>", line 2674, in <module>
TypeError: _type_ must have storage info
Though the same is executing in the console.
Please have a look and say if you can help.
09-24-2019 07:17 AM
Hi akki1811,
this was long ago but let's try. I need some information:
- The VI
- The python script
- The exact version of Python and comtypes
candidus
09-26-2019 12:46 PM
OK, I think I can explain the errors.
The first one:
_ctypes.COMError: (-2147352567, 'Exception occurred.', ('LabVIEW : VI execution terminated by the server.', 'LabVIEW', None, 0, 0))
indicates that you aborted the execution manually.
The second one:
TypeError: _type_ must have storage info
means the type library wasn't imported yet. This happens only once, all further runs of the script shouldn't result in this error.
According to your description I think your VI never finishes execution. Please check that your VI executes properly as a subVI.
09-26-2019 04:25 PM
Yep, I have been working on the same thing, and have been very surprised at the lack of documentation that exists about how to control LabVIEW from Python using the COM interface, so I thought I would share a few things I have learned.
I am just trying to read data into a VI, have the VI do something, and then get data back out. I want the VI to be able to run as a sub VI behind-the-scenes, as well as when it is displayed to the user. Easy, right? I guess not. I have tried lots of things, including early binding using the win32com.client.gencache.EnsureDispatch(), and EnsureModule() functions. I have tried late binding and the comtypes.CoInitialize() function, among others. There seem to be problems at every turn, and I am quite disappointed at what I would have expected to be a fairly straightforward and well-documented interface.
Well, at least I've cobbled together some work-arounds that seem to handle most things. I could go on finding work-arounds forever, but I figured I'd better move on. I am using LabVIEW 2017 (v 17.0, 64-bit), Python 3.6.5 (Anaconda 3.5.2.0, 64-bit), and comtypes 1.1.4. Here is a little summary of the files I am including:
ExampleData.vi and ArraySelect.vi are the VI's that are run.
LabVIEW_Control_DD.py (DD = dynamic dispatch)
This one runs the best of all the methods I have tried. The only problem remaining with this file is that you have to open the front panel of each VI, or run it before you call it. Otherwise, you cannot get data back out using the GetControlValue() function.
LabVIEW_Control_CT.py (CT = comtypes)
(1) On first run, it produces "TypeError: _type_ must have storage info", which persists until something else is run - i.e. running the LabVIEW_Control_DD.py file. This may be related to the comment at the top where GetModule() fails at times.
(2) It gives a Type Mismatch COM error when automation.py does not succeed as the ArraySelect VI is run. I don't know how to resolve this at present.
LabVIEW_Control_EB.py (EB = early bound)
Right now this file does not run. It produces AttributeError: '<win32com.gen_py.LabVIEW 8.0 Type Library._IApplication instance at 0x2613633932760>' object has no attribute 'GetVIReference'. And with early binding, Python is not aware of the _FlagAsMethod() function, so you cannot tell it that there are other methods. Something is going wrong between the labview.tlb type library and the makepy.py utility. This needs to be fixed.
I hope that these files can help someone else not have to spend the time that I did.
It would be great if NI could see if they can update the labview.tlb type library to resolve any of these problems, and then provide some more comprehensive examples.
Good Luck!
09-27-2019 02:28 AM - edited 09-27-2019 02:36 AM
TypeError is coming sometimes only, else it executes. I am passing the type lib path to GetModule. There something wrong with the labview.tlb as mentioned by steveh01, which even I am unable to resolve.
to the second one I am aborting the VI manually because it is not responding and also not taking the timeout data.
09-27-2019 09:57 AM
to the second one I am aborting the VI manually because it is not responding and also not taking the timeout data.
I created a very simple VI and can execute it using the script you sent me without problems. That's why I doubt that Python or COM is the culprit here: I suspect that your VI doesn't finish execution regardless how you call it. Does it return if you call it as a mere subVI in LV?
10-03-2019 05:14 AM - edited 10-03-2019 05:16 AM
It involves NI hardware during execution after the input parameters are being passed in LV, Without python if I run, it does return as mere subVI on call. With hardware interaction I did use PyVISA.
Also, TypeError with GetModule(), happens often with me not only for one time.