06-16-2010 01:20 PM
Hello all,
Attached are the VIs I'm having trouble with. The main VI is connection, which has a callback VI that is testCallback.
The issue, as I understand it, is that the OnGazeData event is not firing, as I've created the callback VI to create and write to a file; however, the file is not created.
My first question is whether or not the 500 ms wait inside the loop will block out my events from firing.
I cannot redistribute the .dll that defines these functions, but I will try to describe what OnGazeData does; the rest should be fairly self-explanitory from the VIs attached.
OnGazeData is fired anytime the attached device has data to be interpreted. The event's data will be a structure called gazeData. There are a number of elements to the structure, including a timestamp as well as left and right eye pupil size. All variables in the structure are either integers or floating point numbers.
Strangely enough, the C++ code that ships with the device functions in, as far as I can tell, the same manner as my connection VI. OnGazeData fires, and the C++ program displays the outputs in a window.
In the end, I'd really like to be able to use Labview to interpret the gazeData that OnGazeData fires with, hence the User Parameter (which will eventually be changed to a varient, or a cluster, I'm really unsure).
Is there anything that stands out to you that could be causing the problems? I realize that it is difficult to debug without the actual .dll to access the same functions that I have. I've been banging my head against this VI for a few weeks now, and I'm really at a loss for what could be changed/improved now.
This is my first Labview project, please forgive my ignorance. Thank you for taking the time to look over what I have to say.
Solved! Go to Solution.
06-17-2010 04:56 AM
Hello,
I can't give you a solution, just some hints:
The 500ms timing inside the loop won't block your events from firing. The callback VI is a reentrant VI that runs independently from your loop.
There's an easy way to check whether you get events: Disable reentrant execution of your callback VI and open its front panel: The timestamp changes when an event occurs. If that doesn't happen you don't receive events. That might be more convenient than writing a file.
But now a real problem: I assume your gazeDate structure is declared as a struct with a GUID in the IDL file of the COM server. If that's the case you have no chance to use it in LabVIEW. Structs are not automation compatible, LV can only handle automation compatible types. Perhaps that's also the reason why you don't receive events.
If you have the C++ code of the COM server you could try to change the gazeData struct parameter to a Variant
containing a SafeArray of floating point numbers: In LV you can then use the "Variant To Data" primitive to extract the array.
Another workaround might be creating an .NET interop DLL of your COM server and use the .NET object in LV but I never tried this myself.
06-17-2010 12:36 PM
Hi candidus,
I'm glad to hear the 500ms timing isn't the culprit.
I unchecked Reentrant and saw no change in the timestamp; it seems it's not firing at all. Thanks for that, that's much easier to test with.
Re: GUID, IDL, COM server:
I think I mispoke in the title; I don't think it's a COM event so much as it's a component. I'm really not sure what a COM server is, nor how to see if there even is an IDL. The documentation I'm reading is not from a native English speaker, and I'm having a hard time deciphering it at all.
I believe the underlying structure is just a DLL on my machine. Unfortunately, unless the research I'm doing now turns up anything, I don't think I have the source code for it, just the .dll that shipped with the device. I do have a book of essentially prototypes of each function, and a description of the members, arguments, returns, etc.
The "class" information showed up on connection.vi's control under the "Select ActiveX Class" option.
So I suppose my revised questions would look something like this:
Again and as always, thanks for the help!
06-17-2010 02:31 PM
Hello Evan,
I compared your VI to an example VI that spawns an events and I noticed that you haven't specified what event you want the code to act upon. If you look at the example called ActiveX Event Callback for Excel VI in the Example Finder, it puts every day of the week in first sheet of a workbook when a new workbook is created. On the block diagram, the register Event Callback specifies the event to NewWorkbook which correspond to the user creating a new workbook. What is the name of the event that corresponds to receiving data for this piece of code?
06-17-2010 06:15 PM
Re: GUID, IDL, COM server:
I think I mispoke in the title; I don't think it's a COM event so much as it's a component. I'm really not sure what a COM server is, nor how to see if there even is an IDL. The documentation I'm reading is not from a native English speaker, and I'm having a hard time deciphering it at all.
So I suppose my revised questions would look something like this:
- How do I discover whether my structure is indeed declared as a struct with a GUID in the IDL file of the COM server
- Failing that, can anyone point me in the right direction as far as writing a wrapper .dll, preferably one that easily integrates into LV via .Net or ActiveX). Callback, .Net, and ActiveX are all fairly new to me.
Hi Evan,
you didn't mispoke in the title, COM server and COM event is correct. A little about the internals of a COM Server:
COM Servers are built using IDL files. IDL means "interface definition language", an IDL file is a plain text file that looks a bit like a C header file. It contains interface definitions. Interfaces consist of properties and methods, these are the ones you can access via Property Nodes and Invoke Nodes from LV. Every interface has a GUID, a globally unique identifier. The IDL file is compiled into a type library, a binary representation of the IDL file. LV reads the interface and coclass information from the type library. If you have Visual Studio installed you can view type libraries using a tool called OleView.exe . Thus you could find out whether structs are used. Sounds complicated, but that's COM 🙂
If you have to deal with automation incompatible types (e.g. struct) you need a wrapper. With a little luck you needn't write C++ but can create a .NET wrapper DLL instead: The .NET SDK provides a tool called tlbimp that you can use to accomplish this task. It's a command line tool that takes the name of the COM DLL as parameter. After creating the interop DLL with tlbimp you can use it in LV. Structs are also exported as .NET objects so you can create and access them.
Hope that helps.
06-18-2010 11:39 AM
Jim,
The name of the event is OnGazeData. I would imagine that it's not showing up in my VI because A) the machine I post from does not have the .dll (the machine that does have the .dll has no Internet access); and B) likely your machine doesn't have it either.
candidus,
I'm downloading the .Net SDK now to try this. Would this incompatible typing cause the event to not fire, or is this another issue that I need to work out?
06-21-2010 04:58 AM
I'm downloading the .Net SDK now to try this. Would this incompatible typing cause the event to not fire, or is this another issue that I need to work out?
You have to find out. At least you should be able to overcome the struct limitation but there still might be lurk other issues.
07-07-2010 12:41 PM
I'm still in the process of wrapping the .dll, but a few more questions popped up.
First, I was wrong about the struct being passed. What's actually being passed is a pointer to a struct. Is there a way I can handle this in LV (dereference the pointer and get the data).
Second, I'm still unconvinced that the problem will be resolved with a new .NET .dll. It just seems like there's something else in play here I haven't found. Not to downplay candidus's help, but could someone put out a second opinion regarding this?
Last, and I doubt I'll get any support for this here, as I'm writting the wrapper .dll in C#, I find myself wanting to hook the original .dll's events, but I'm unsure how to do this. Can anyone lend some insight on this, or perhaps point me in the right direction?
Thanks so much in advance 😃
07-08-2010 01:59 PM
Sorry to double-post, but I feel it's worth mentioning. I did try to use the TlbImp tool in the .NET SDK. When I imported this into LV, however, the resulting VI, more specifically the automation reference, will not let me Register Event Callback as if there are no events at all.
Attached is the new VI I'm working with and the .dll created from TlbImp. Obviously connect shouldn't work as you don't have the piece of hardware.
07-08-2010 03:01 PM
Solved. I had wired the tlbimp VI incorrectly; the event now fires correctly! Thank you so much, candidus!