Professional OPC
Development Tools


Access returned array elements from C++

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.


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.

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

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;
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.

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.

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

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"";
	//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));
	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);
		_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()
	ClientPtr = NULL;
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.218 seconds


 Recommend this on Google