Professional OPC
Development Tools

logos

Online Forums

Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.

Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.

Do not use the Contact page for technical issues.

Access returned array elements from C++

More
29 Sep 2016 13:53 #4402 by support
NO problem. This is a concrete question that I will have look at. It is even possible that the server has not filled it in correctly, or that we have a bug in array conversions.

Questions:

1. I assume that you observe this with our public demo server, right? Or is it a different server?

2. Do you actually need to work with value arrays in you project (this is just to assess the priority of the issue)?

Thank you
The following user(s) said Thank You: Vasanth

Please Log in or Create an account to join the conversation.

More
29 Sep 2016 12:57 - 29 Sep 2016 13:53 #4401 by Vasanth
Hi,

Sorry to bother you.

I am trying to read SafeArray from DAVtqPtr->Value.parray, But, while accessing data it shows unable to read memory(pVals value always goes null). I am trying to get safearray of R8 (real values). Please confirm me that i am reading correct safearray or something else. My code is below,
                SAFEARRAY* saValues = DAVtqPtr->Value.parray;
		double* pVals;
		HRESULT hr = SafeArrayAccessData(saValues, (void**)&pVals); // direct access to SA memory
		if (SUCCEEDED(hr))
		{
			long lowerBound, upperBound;  // get array bounds
			SafeArrayGetLBound(saValues, 1, &lowerBound);
			SafeArrayGetUBound(saValues, 1, &upperBound);
 
			long cnt_elements = upperBound - lowerBound + 1;
			for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
			{
				double lVal = pVals[i];
				std::cout << "element " << i << ": value = " << lVal << std::endl;
			}
			SafeArrayUnaccessData(saValues);
		}
		SafeArrayDestroy(saValues);
I just wanted to confirm whether am reading correct safearray or pro-grammatical issue i am facing. Any help highly appreciated.

Thanks for understanding
Last edit: 29 Sep 2016 13:53 by support.

Please Log in or Create an account to join the conversation.

More
28 Sep 2016 15:35 #4400 by support
The ToString method does not display contents of the arrays, this is by design.

All incoming values are represented in Windows VARIANT. That includes array values. You can examine the incoming DAVtq->Value, and you will find a VARIANT there that contains a "safe array".

Handling these is a standard Windows C/C++ programming topic that is outside of the scope of these forums. You should be able to find information about in Windows documentation, ATL/MFC documentation, Google-ing for it, etc.

Best regards
The following user(s) said Thank You: Vasanth

Please Log in or Create an account to join the conversation.

More
28 Sep 2016 11:50 - 28 Sep 2016 15:31 #4398 by Vasanth
Hi,

Could you please help me on reading array tags like Dynamic/Analog Types/Double[].
Array tags values are showing empty in console app.

BTW, I have optimized your code and you can use it if you want. Thankyou.
//conStr should read from ini file
	CComBSTR conStr = L"http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx";
 
	//no of tags should read from CSV file
	int noOftags = 4;
 
	std::vector<CComBSTR> itemId;
	itemId.push_back(L"Dynamic/Analog Types/Double");
	itemId.push_back(L"Dynamic/Analog Types/Double[]");
	itemId.push_back(L"Dynamic/Analog Types/Int");
	itemId.push_back(L"Dynamic/Analog Types/Int[]");
 
	CComSafeArray<VARIANT> ArgumentsArray(noOftags);
 
	for (int i = 0; i < noOftags; i++)
	{
		_DAReadItemArgumentsPtr ReadItemArguments1Ptr(_uuidof(DAReadItemArguments));
		ReadItemArguments1Ptr->ServerDescriptor->UrlString = conStr.m_str;
		ReadItemArguments1Ptr->ItemDescriptor->ItemId = itemId[i].m_str;
		ArgumentsArray.SetAt(i, _variant_t((IDispatch*)ReadItemArguments1Ptr));
	}
 
	LPSAFEARRAY pArgumentsArray = ArgumentsArray.Detach();
	CComSafeArray<VARIANT> ResultArray(ClientPtr->ReadMultipleItems(&pArgumentsArray));
	ArgumentsArray.Attach(pArgumentsArray);
 
	for (int i = ResultArray.GetLowerBound(0); i <= ResultArray.GetUpperBound(0); i++)
	{
		_DAVtqResultPtr DAVtqResultPtr(ResultArray[i]);
 
		_ExceptionPtr ExceptionPtr(DAVtqResultPtr->Exception);
		if (ExceptionPtr != NULL)
		{
			_variant_t exceptionAsString(ExceptionPtr->ToString);
			_tprintf(_T("results(%d).Exception.ToString(): %s\n"), i, exceptionAsString.bstrVal);
			continue;
		}
 
		_DAVtqPtr DAVtqPtr(DAVtqResultPtr->Vtq);
		_variant_t vtqAsString(DAVtqPtr->ToString);
		_tprintf(_T("results(%d).Vtq.ToString(): %s\n"), i, vtqAsString.bstrVal);
	}
 
	// Release all interface pointers BEFORE calling CoUninitialize()
	ResultArray.Destroy();
	ClientPtr = NULL;
	itemId.clear();
Last edit: 28 Sep 2016 15:31 by support.

Please Log in or Create an account to join the conversation.

Moderators: support
Time to create page: 0.051 seconds