DIAdem

cancel
Showing results for 
Search instead for 
Did you mean: 

How to get Channel From Name and how to get large Chunks of Data in VC-GPI-Dll?

Hi!

I am having some trouble with the GPI-interface (in Diadem 9.1 SP2, newest GPI from website). I want to create a function that you can pass a name of a channel as a parameter into and then do some calculations on that channel. The problem is that the only functions I found work just on a channel number, not on a name. So I need to get a channel number from the channel name. The only solution I found so far is to use nChannelObjListCreate to create a list of all channels, and then to go through that list and do a string-compare. Ok.. that's not a good solution, but the only one I found so far..
The Problem now is, that the values in the list are something like [2]/Time, but they should be Measurement1/Time. How can I solve that problem and either match the names or just solve the problem stated above in a nicer way?

I also want to transfer some larger (>1M) amounts of data into the GPI-Dll, sometimes as much as 10-100M values. My solution now is to 1.000.000 x call the lpdDataObjChannelValueGet function. Again.. not a nice solution, but the only one I found..
I also tried to get the data via OLE (using VC and not VB), since there is a function to get a whole range of values at once. But unfortunately, I can't get it to work.. I simply put a variant into the function, but it doesn't contain any usable data when the OLE-call returns. In the description, (which is VB only..) it states that the variant doesn't have to be initialized. So I don't know where the problem might be. Also, I noticed that the counter of DIAdem, showing external references to the program (in the taskbar) does increase each time I call the respective function in the GPI-Dll, even though I do both a release and afterwards a CoUnitialize. That should be sufficient to decrease the counter, shouldn't it?

Many thx for any help or hints!!

Best regards,
diadev
0 Kudos
Message 1 of 7
(4,308 Views)
Hi Diadev,
 
Which OLE command are you using to pick up the values?  Can you show me your call to Invoke please?  What does the VARIANT look like that you are getting back?  Specifically, what is the value of vt on your VARIANT?
 
If this command returns a range of values I'd expect it to contain a SAFEARRAY.  If so, then the value of vt should be VT_SAFEARRAY (27).  But a VARIANT can be a bit "deeper" than that.  It could also contain a further VARIANT.  If the value of vt contains VT_BYREF (0x4000) and VT_VARIANT (12), then you need to look in the pvarVal of the VARIANT in order to get further.
 
If the command is supposed to return you its values in a parameter that you pass it instead of in a return value.  You may be setting up the parameters you pass to it incorrectly.  It could be that you need to be passing it a BYREF VARIANT.  Setting up the VARIANT would look something like this:
  VARIANT Val;  ::VariantInit(Val);
  V_VT(&Vargs[i]) = VT_BYREF | VT_VARIANT
  V_VARIANTREF(&Vargs[i]) = &Val;
Vargs is the VARIANTARG* hanging on your dispparams.  The value you are looking for would be found in Val after the call to Invoke returns.
 
If you really are getting just plain trash back, then I may not be able to help you.
 
Myrle
******************
For tips and tricks on creating VBScript DataPlugins go to http://dataplugins.blogspot.com.
0 Kudos
Message 2 of 7
(4,291 Views)
Hi Myrle!

I use the commands ValueRangeGet and ChnLengthGet. I tried it in VB, and it works fine enough. In the documentation it says explicitly to put in an empty VARIANT. So I just declare a VARIANT and use VariantInit on it (which simply set the vt to VT_EMPTY). I then use a function invoke ( Invoke(pDispatchToDataSheet, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("ValueRangeGet"), "IIII&v", 1, 1, 100, 1, &vChannelTime); ) which is from some sample source code I found to simplify the use of COM and OLE under VC++. I already succefully used it (after something like a week of tweaking parameters..) to set some values in DIAdem. So I assume that this code is working. It is quite a shame there is no examples for Visual C programmers..

The VARIANT, when it returns, does contain exactly the value that it had when I called the function. So I suppose that means that DIAdem doesn't do anything with it.

Also, the other strange thing is, that even though I call

pDispatchToDataSheet->Release();
pDispatchToCommand->Release();
CoUninitialize();


with the pointers coming from

hr=CoCreateInstance(clsidDiademToCommand,NULL,CLSCTX_SERVER,IID_IDispatch,(void**) &pDispatchToCommand);
    if(!SUCCEEDED(hr)) {
        AfxMessageBox("Could not initialize the Diadem Dispatcher interface.");
        CoUninitialize();
        return;
    }


, the reference counter is constantly increased, and I can close DIAdem only via the icon in the taskbar or the task manager. I think that's rather odd.. and should I want to deliver this solution to a customer, even if I manage to fix the problems above, it renders the whole thing rather useless.

Best regards and many thx for your help!
diadev
0 Kudos
Message 3 of 7
(4,285 Views)

Hi diadev,

I looked in the DIAdem documentation for ValueRangeGet and ChnLengthGet, and they are both the kinds of functions that I would expect to take by ref variants as I described in my first post.  The actual return value is used for a success code and the information you want gets placed in a VARIANT that you pass in.  VBScript does this for you automatically which is why this is so much easier under VBS.

Unfortunately, I'm not familiar with your library.  I hope you have the source code for it.  It looks like it takes a variable length list of parameters and the string after the method name says which parameters are coming.  This is probably the information that it uses to pack the dispparams together.  Possibly that function does not have support for by ref variants or has a bug in dealing with them, but since I don't know the function I can't say for sure.  If I were you, I'd debug into that function and see how it does the actual packing of the arguments for it's call to IDispatch->Invoke.

As far as the ref counting of the dispatch map goes, I can't say much.  I do know that the couple of times I've "pulled" the DIAdem dispatch map that I haven't had reference leaks, or that if I have had them that I eventually found the problem in my own code.  But I've also never called these particular functions.  Again, you may want to debug into your library and see what it actually does with the dispatch pointer that you pass into it.

You can also check for relationships between the ref count and the things you do with the dispatch map.  Release returns the current refcount.  Using that, you will at least be able to determine which object it is that is not properly reference counted.  If the ref count seems to be proportional to the number of calls to your Invoke function, then that is a strong indicator that the problem lies somewhere in the Invoke function.  Otherwise try to find a relationship between the number of leaked references and some other action you perform in your code.  Don't forget that QueryInterface also increments the reference count while you're checking.

I hope that helps,
Myrle

P.S.  The problem with making examples for C programmers is that then you have to support them.  And someone who's good enough in C to support a C programmer is usually a C programmer himself and not in support. 🐵

******************
For tips and tricks on creating VBScript DataPlugins go to http://dataplugins.blogspot.com.
0 Kudos
Message 4 of 7
(4,272 Views)
Dear Myrle!

Many thanks for your help and your suggestions!

After toying around for some time I decided that getting each value seperately is a decent enough solution. After all, due to memory limitations, it is not possible to have more than ~40M values on a 512MB machine at the one time anyway. Actually DIAdem slows down at far less to a complete crawl already (you need time and amplitude, double has 8 bytes and so on..).. so getting each value seperately is ok. (Just 10M function calls or so. Only takes a second.)

So I also could drop the idea of using OLE Automation to get the values. The same goes for the channel names. I just use integer values now, so it is up to the user to find out which channel number to pass to my algorithm.

Sorry for the late reply, I had quite a lot of stuff to sort out. Thx for your help again!

Best wishes,
diadev
0 Kudos
Message 5 of 7
(4,203 Views)

Hello diadev,

Looks like Myrle has already answered most of your questions. If you want to find the channel number from the channel name, here is what you can do :

use "nDIAdemVarGet" which is designed to get the value of a variable. Instead of referring to a variable directly, you send "CNO(<channelname>)" to use the DIAdem function CNo to convert from channel name to number. The return value from nDIAdemVarGet will give you the number..

One thing I'd like to ask is whether you can describe the use case for your GPI DLL. Are you trying to import the data from a file ? If so, DataPlugins may be a better alternative. Just let me know whether you would like to get more information.

 Andreas

0 Kudos
Message 6 of 7
(4,196 Views)
Hi Andreas!

Thx for your idea, it sounds very good!

I am using the Dll to get data from DIAdem (from a measurement), process this data and then to output the results to the report generator. Actually that process is evoked from a LabView application which is also responsible for calling the report generator (the dll only stores the results in internal DIAdem variables).

Best regards,
diadev
0 Kudos
Message 7 of 7
(4,189 Views)