From 04:00 PM CDT – 08:00 PM CDT (09:00 PM UTC – 01:00 AM UTC) Tuesday, April 16, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing the DataSocket only using nids.dll

Solved!
Go to solution

Hello,
I have the task to communicate to a program, written in LabView, just by communicating through the data socked, using only the INIDSCtl and ICWData interfaces of nids.dll. The communication in the direction that I send data to the LabView program works, but I have problems receiving the data. The data that are sent are an array of 4 float ( 32 bit floatingpoint) values. I can see in the Data Socket Server Diagnostics that there are really packages sent, but I cannot receive those data.
I am programming this in C++ using MS Visual Studio 6.0. I do not have any other tools ( like Measurement Studio ).

The working code to send just a simple 16 bit integer value is (I removed all error checking for shorter code)


#import "C:\windows\system32\nids.dll" raw_interfaces_only, no_namespace, named_guids
...
HRESULT hr = g_pNIDSCtl.CreateInstance("CWDSLib.CWDataSocket");
...
ComBSTR bstrURL(_T("dstp://localhost/emmenu_to_ts"));

hr = g_pNIDSCtl->put_URL( (bstr_t)bstrURL );
hr = g_pNIDSCtl->put_AccessMode( cwdsWrite );

short b;
hr = g_pNIDSCtl->SyncConnect( 30000, &b );

ICWData *pData = NULL;
hr = g_pNIDSCtl->get_Data( &pData );

CComVariant varStart( (short)1 );
hr = pData->put_Value( varStart );
pData = NULL;

hr = g_pNIDSCtl->Update();

hr = g_pNIDSCtl->Disconnect();


However the code to retrieve the data that is not working is as follows

CComBSTR bstrURL(_T("dstp://localhost/ts_to_emmenu"));

hr = g_pNIDSCtl->put_URL( (bstr_t)bstrURL );
hr = g_pNIDSCtl->put_AccessMode( cwdsRead );

short b;
hr = g_pNIDSCtl->SyncConnect( 30000, &b );

ICWData *pData = NULL;
hr = g_pNIDSCtl->get_Data( &pData );

CComVariant varVal;
hr = g_pNIDSCtl->Update();

hr = pData->get_Value( &varVal );
//
// HERE varVal is always 0, independent of the values in the data socket ? ? ?
//
pData = NULL;

hr = g_pNIDSCtl->Disconnect();



My question: Is it even possible to retrieve an array of 4 floats using only the interfaces of nids.dll and if yes, can someone push me in the right direction or give me some hints.

Thanks in advance
Peter

 

0 Kudos
Message 1 of 14
(4,296 Views)

Hi there

 

Just a wild guess:

 

In case "dstp://localhost/ts_to_emmenu" is a dynamically created item your write - code has to keep the items object instance in memory until the item is read by the read object instance. Don't call g_pNIDSCtl->Disconnect() until the read - code has finished, otherwise the item will be deleted from the server and created new by the read - code, thus containig no data.

 

Or create a static item using the dstp server manager!

Best regards
chris

CL(A)Dly bending G-Force with LabVIEW

famous last words: "oh my god, it is full of stars!"
0 Kudos
Message 2 of 14
(4,282 Views)

Hi Chris,

 

I use different URLs to read and write. Thus, the write code should (hopefully) not interfere with the read code. The basic idea is that I send a single value to the LabView program ( like some trigger ) and then it starts sending data independently.

This data I want to access, but I have the feeling that the reading itself is programmed wrong ( e.g. something missing, wrong methods called etc. )

 

Thanks so far 

 Peter 

0 Kudos
Message 3 of 14
(4,277 Views)

Oh, i see.

 

I wrote a little app in C# Express, and it works perfectly well.

 

I used your code, same methods/propertys in the same order as you did. Run VI\dstp_cs_LV2CS.vi and then \dstp_cs\bin\Release\dstp_cs.exe. Maybe there's something wrong on the LV side?

Best regards
chris

CL(A)Dly bending G-Force with LabVIEW

famous last words: "oh my god, it is full of stars!"
Message 4 of 14
(4,272 Views)

Hello Chris,
I have only LabView7 here so I cannot see your vi program. Also the C# program did not send any output ( just an empty command window, only a few milli seconds before closing some text starting with 'system' appears ).

My question: What data does dstp_cs_LV2CS.vi generate? A simple float (single) value or an array of floats ?

 

Thanks for your effords so far.

 

Peter 

0 Kudos
Message 5 of 14
(4,249 Views)

Hi there

 

attached is the screenshot of the LV app. Make sure you have .NET Framework 2.0 or later installed. Take a look at the .cs source file.

Best regards
chris

CL(A)Dly bending G-Force with LabVIEW

famous last words: "oh my god, it is full of stars!"
0 Kudos
Message 6 of 14
(4,247 Views)

Hello Chris,

 

 

we created simple LabView test programs. One that only sends a single value to DS ( same as you did it ) and here we are able to read the data from the DS.

 

But the second LV test program sends an array of 4 values  (32bit floating point) and then the reading program failed. The Data method returns a VARIANT set to VT_I4 which is completely wrong and the value is always 0.

 

My impression is: As soon as an array is involved, reading the DS from an external C++/C# program is no more possible, or at least it must be done completely different, but how ???

 

If you modify your LV program in a way that it sends an array, are you able to read the data from the DS ?

 

Best regards

 Peter 

 

0 Kudos
Message 7 of 14
(4,226 Views)

It's possible, I did it some time ago but it's a bit more complicated:

 

You also need a hidden or messageonly window with its own message pump to process your incoming COM calls.

 

Create a second thread, don't forget to call CoInitializeEx(), creata a window with a message pump and keep that thread alive until you finished reading.

 

0 Kudos
Message 8 of 14
(4,221 Views)

Hello candidus,

 

do you have some example code on what messages are to be processed ? Or some description/documentation ?

 

Best regards

 Peter 

0 Kudos
Message 9 of 14
(4,205 Views)
Solution
Accepted by topic author PEESPE

Hello Peter,

 

Sorry I mixed some things up... I really needed a window because I wanted to be able to use INIDSCtl.SelectURL() .

But it is unecessary for using DataSocket. The important things are:

 

1. Call CoInitializeEx() with COINIT_MULTITHREADED parameter.

2. After connecting to server, call INIDSCtl.GetStatus() repeatedly until it returns cwdsConnectionActive.

3. Call INIDSCtl.Update() and read your data.

 

Here is a quick and dirty example which you can try in conjunction with "DS Writer.vi" example:

 

#define _WIN32_WINNT 0x0501

#include <windows.h>
#include <comip.h>
#include <process.h>

#include <iostream>

#import "nids.dll" no_namespace

int main()
{
  HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  {
    // Create DataSocket instance.
    INIDSCtlPtr ds;
    hr = ds.CreateInstance(__uuidof(CWDataSocket));

    // Connect to server.
    hr = ds->ConnectTo(_bstr_t(L"dstp://localhost/wave"), cwdsRead);

    // Wait until connection established.
    CWDSStatus status;
    while ((status = ds->GetStatus()) == cwdsConnecting)
    {
      Sleep(100);
    }

    // Get data.
    while ((hr = ds->Update()) == S_OK)
    {
      if(ds->GetDataUpdated() == VARIANT_TRUE)
      {
        _variant_t retVal = ds->GetData()->GetValue();
        // check the type of the VARIANT. It must be an array of double.
        if (V_VT(&retVal) != (VT_ARRAY | VT_R8))
          throw _com_error(E_FAIL);

        // Unpack array.
        SAFEARRAY* psa = V_ARRAY(&retVal);
        if (psa == NULL)
          throw _com_error (E_POINTER);

        // It must have one dimension.
        if (psa->cDims != 1)
          throw _com_error(E_FAIL);

        double HUGEP* vals;
        HRESULT hr = S_OK;
        if (FAILED (hr = SafeArrayAccessData(psa, (void HUGEP**) &vals)))
          throw _com_error (hr);

        for (unsigned long i = 0; i < psa->rgsabound[0].cElements; i++)
        {
            std::cout << vals[i] << std::endl;
        }

        // Array no longer needed.
        if (FAILED (hr = SafeArrayUnaccessData(psa)))
          throw _com_error (hr);
      }
    }
  }

  CoUninitialize();

  return 0;
}
 

Message Edited by candidus on 08-05-2009 03:54 AM
Message 10 of 14
(4,187 Views)